Subnet Mask Explained — How Subnetting and Network Masks Work
A subnet mask separates the network portion from the host portion of an IP address. Here's how subnet masks work, how to read CIDR notation, and how to calculate usable hosts...
A subnet mask is a 32-bit number that identifies which part of an IP address is the network and which part is the host. It’s how routers know whether two IP addresses are on the same network or need routing between networks.
Use the Subnet Calculator to calculate subnet ranges, usable hosts, and network details.
How subnet masks work
Every IPv4 address and subnet mask is 32 bits. The mask uses 1s for the network portion and 0s for the host portion:
IP address: 192.168.1.100
Subnet mask: 255.255.255.0
Binary:
IP: 11000000.10101000.00000001.01100100
Mask: 11111111.11111111.11111111.00000000
└─── network portion ───┘ └─ host ─┘
AND operation reveals the network address:
IP: 11000000.10101000.00000001.01100100 (192.168.1.100)
Mask: 11111111.11111111.11111111.00000000 (255.255.255.0)
AND: 11000000.10101000.00000001.00000000 (192.168.1.0)
The network is 192.168.1.0. Any IP from 192.168.1.1 to 192.168.1.254 is on this network.
Common subnet masks
| CIDR | Subnet Mask | Network bits | Host bits | Usable hosts |
|---|---|---|---|---|
| /8 | 255.0.0.0 | 8 | 24 | 16,777,214 |
| /16 | 255.255.0.0 | 16 | 16 | 65,534 |
| /24 | 255.255.255.0 | 24 | 8 | 254 |
| /25 | 255.255.255.128 | 25 | 7 | 126 |
| /26 | 255.255.255.192 | 26 | 6 | 62 |
| /27 | 255.255.255.224 | 27 | 5 | 30 |
| /28 | 255.255.255.240 | 28 | 4 | 14 |
| /29 | 255.255.255.248 | 29 | 3 | 6 |
| /30 | 255.255.255.252 | 30 | 2 | 2 |
| /32 | 255.255.255.255 | 32 | 0 | 1 (host only) |
Usable hosts formula: 2^(host bits) - 2
The -2 subtracts the network address (all 0s) and broadcast address (all 1s), which can’t be assigned to hosts.
CIDR notation
CIDR (Classless Inter-Domain Routing) notation combines the IP address and prefix length:
192.168.1.0/24
└── /24 means 24 bits are the network portion
/24 is equivalent to subnet mask 255.255.255.0.
The prefix length equals the number of consecutive 1-bits in the subnet mask:
255.255.255.0 = 11111111.11111111.11111111.00000000 = 24 ones → /24
255.255.255.128 = 11111111.11111111.11111111.10000000 = 25 ones → /25
255.255.0.0 = 11111111.11111111.00000000.00000000 = 16 ones → /16
Subnet components
For 192.168.1.0/24:
Network address: 192.168.1.0 — identifies the subnet
Broadcast address: 192.168.1.255 — sends to all hosts in subnet
First usable host: 192.168.1.1
Last usable host: 192.168.1.254
Usable hosts: 254 (256 - 2 for network and broadcast)
Calculating subnet ranges
For 10.0.0.0/26:
- Prefix = 26, so host bits = 32 - 26 = 6
- Hosts per subnet = 2^6 = 64
- Usable = 64 - 2 = 62
Network address: 10.0.0.0
First host: 10.0.0.1
Last host: 10.0.0.62
Broadcast: 10.0.0.63
For 172.16.5.0/25:
- Host bits = 32 - 25 = 7
- Hosts per subnet = 128
- Usable = 126
Network address: 172.16.5.0
First host: 172.16.5.1
Last host: 172.16.5.126
Broadcast: 172.16.5.127
Subnetting: dividing a network
Divide 192.168.1.0/24 into 4 equal subnets:
4 subnets requires 2 additional bits (2^2 = 4). Prefix extends from /24 to /26:
Subnet 1: 192.168.1.0/26 (hosts: .1 – .62)
Subnet 2: 192.168.1.64/26 (hosts: .65 – .126)
Subnet 3: 192.168.1.128/26 (hosts: .129 – .190)
Subnet 4: 192.168.1.192/26 (hosts: .193 – .254)
Each subnet has 62 usable hosts.
Checking if two IPs are on the same subnet
import ipaddress
def same_subnet(ip1, ip2, prefix_len):
network1 = ipaddress.ip_interface(f'{ip1}/{prefix_len}').network
network2 = ipaddress.ip_interface(f'{ip2}/{prefix_len}').network
return network1 == network2
print(same_subnet('192.168.1.50', '192.168.1.100', 24)) # True
print(same_subnet('192.168.1.50', '192.168.2.100', 24)) # False
# Is IP in subnet?
network = ipaddress.ip_network('192.168.1.0/24')
ip = ipaddress.ip_address('192.168.1.100')
print(ip in network) # True
// Simple subnet check with bitwise operations:
function ipToInt(ip) {
return ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet), 0) >>> 0;
}
function sameSubnet(ip1, ip2, mask) {
const maskInt = ipToInt(mask);
return (ipToInt(ip1) & maskInt) === (ipToInt(ip2) & maskInt);
}
console.log(sameSubnet('192.168.1.50', '192.168.1.100', '255.255.255.0')); // true
console.log(sameSubnet('192.168.1.50', '192.168.2.100', '255.255.255.0')); // false
Cloud networking subnets
AWS, Azure, and GCP use VPC (Virtual Private Cloud) with subnets:
VPC: 10.0.0.0/16 (65,534 IPs)
Subnets:
Public subnet: 10.0.1.0/24 (254 hosts, internet-facing)
Private subnet: 10.0.2.0/24 (254 hosts, internal only)
DB subnet: 10.0.3.0/24 (254 hosts, database tier)
AWS reserves 5 IPs per subnet: first 4 and last 1:
10.0.1.0— Network address10.0.1.1— VPC router10.0.1.2— AWS DNS10.0.1.3— Future use10.0.1.255— Broadcast
So a /24 subnet in AWS gives 251 usable IPs (256 - 5), not 254.
Related tools
- Subnet Calculator — calculate subnet details
- CIDR Notation Explained — CIDR guide
- IP Address Calculator — IP range calculations
Related posts
- Private IP Address Ranges, Subnets, and CIDR Notation Explained — The three RFC 1918 private ranges, what CIDR notation actually means, subnet mas…
- CIDR Notation Explained — What /24, /16, /8 Mean in IP Addresses — CIDR notation is the slash number after an IP address — /24, /16, /8. It specifi…
- DHCP IP Allocation — How Dynamic IP Assignment Works — DHCP (Dynamic Host Configuration Protocol) automatically assigns IP addresses, s…
- IP Address Calculator — Calculate Network and Host Ranges — An IP address calculator finds the network address, broadcast address, and usabl…
Related tool
Calculate IPv4 subnets — network, broadcast, usable range, wildcard mask. Input CIDR (/24) or dotted mask (255.255.255.0). Binary visualization.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.