The subnet mask draws the line between the network part of an address and the host part. Read it in binary, in decimal, and as a /prefix.
Why: the subnet mask is a run of 1s followed by 0s — the 1s mark the network portion of an address and the 0s mark the host portion, which is how a device decides whether a destination is local or remote. When: every interface has an IP and a mask; you cannot configure one without the other. Where: the "/24" prefix notation is just a count of the 1 bits.
IP 192.168.1.10 11000000.10101000.00000001.00001010
Mask 255.255.255.0 11111111.11111111.11111111.00000000
\_____ network (24 bits) _____/\_ host _/
/24 = 24 one-bits = 255.255.255.0
Network part: 192.168.1 Host part: .10Why: masks appear in three forms — dotted decimal (255.255.255.0), prefix (/24), and binary — and you must convert fluidly between them. When: cert exams and device configs mix all three. Where: Python’s ipaddress module converts instantly so you can check yourself.
import ipaddress
net = ipaddress.ip_network("192.168.1.0/24")
print(net.netmask) # 255.255.255.0
print(net.prefixlen) # 24
print(net.hostmask) # 0.0.0.255 (the inverse/wildcard mask)
# From a decimal mask back to a prefix:
print(ipaddress.ip_network("10.0.0.0/255.0.0.0").prefixlen) # 8Why: within any subnet the first address is the network ID and the last is the broadcast — neither is assignable to a host — so usable hosts = 2^(host bits) − 2. When: this formula decides whether a subnet is big enough for a given number of devices. Where: a /24 has 8 host bits → 256 total → 254 usable.
import ipaddress
net = ipaddress.ip_network("192.168.1.0/24")
print(net.network_address) # 192.168.1.0 (not assignable)
print(net.broadcast_address) # 192.168.1.255 (not assignable)
print(net.num_addresses) # 256
print(list(net.hosts())[0], list(net.hosts())[-1]) # .1 ... .254 (usable)
print(net.num_addresses - 2, "usable hosts") # 254