Subnet masks explained

255.255.255.0 looks arbitrary until you see it in binary. Then it is obvious and stays obvious.

A mask is a line, written awkwardly

A subnet mask says exactly what a CIDR prefix says: where the network part of an address ends and the host part begins. It says it in dotted decimal instead of a count, which is why it looks like a magic number.

A subnet mask is a line drawn through 32 bits The mask marks where the network part of an address ends and the host part begins. A slash 26 means the first 26 bits are network and the last 6 are host, which is 255.255.255.192 in dotted decimal. The mask marks one boundary, and everything else follows from where it sits Address 192.168.1.130 11000000 10101000 00000001 10000010 Mask /26 255.255.255.192 11111111 11111111 11111111 11000000 the boundary 26 network bits, identical for every host here 6 host bits What the host bits give you 6 host bits means 2 to the power of 6, which is 64 addresses in the block. Two are reserved: the lowest is the network address and the highest is the broadcast address, so 62 are usable. Worth memorizing: usable hosts equals 2 to the power of (32 minus the prefix), minus 2. The exceptions are /31, which has 2 usable and no broadcast, and /32, which is a single host.
In binary the mask is all ones, then all zeros, and the changeover is the boundary. Every mask ever written has that shape, which is the fact that makes the rest easy.

So 255.255.255.0 is 24 ones followed by 8 zeros, which is a /24. They are two spellings of one thing, and modern tooling accepts either.

The nine values, which is all you need to memorize

Because a mask is always ones followed by zeros, an octet cannot hold an arbitrary number. There are exactly nine possibilities, and recognizing them on sight removes most of the work.

DecimalBinaryOnesBlock size in that octet
0000000000256
128100000001128
19211000000264
22411100000332
24011110000416
2481111100058
2521111110064
2541111111072
2551111111181
The 256-minus trick

The last column is just 256 minus the decimal value. For 255.255.255.192, that is 256 minus 192 = 64, so blocks are 64 addresses and start at .0, .64, .128, .192. This is the fastest route to an answer under time pressure and it is not a hack: it is the same arithmetic as counting host bits.

A mask with anything else in it is invalid. 255.255.255.100 is not a mask, because 100 is 01100100 in binary and the ones are not contiguous. If you see one, something has been typed wrong.

Binary without a calculator

You need this rarely, and when you do you need it quickly. An octet is eight bit positions with fixed values:

128  64  32  16   8   4   2   1

192  =  128 + 64                      =  1 1 0 0 0 0 0 0
130  =  128 +           2             =  1 0 0 0 0 0 1 0
168  =  128 + 32 + 8                  =  1 0 1 0 1 0 0 0
 10  =         8 + 2                  =  0 0 0 0 1 0 1 0

The method is greedy and takes seconds: start at 128, subtract it if it fits, move right, repeat. Going the other way, add up the positions holding a one.

Hex, for IPv6

IPv6 is written in hexadecimal, where each digit is exactly four bits. That one-to-one mapping is the reason hex is used at all, and it makes conversion mechanical rather than arithmetic.

0 = 0000    4 = 0100    8 = 1000    c = 1100
1 = 0001    5 = 0101    9 = 1001    d = 1101
2 = 0010    6 = 0110    a = 1010    e = 1110
3 = 0011    7 = 0111    b = 1011    f = 1111

db8  =  0000 1101 1011 1000

Split the binary into groups of four from the right, and read each group off the table. No division, no remainders.

Wildcard masks, which are backwards on purpose

Access lists on Cisco equipment and some firewall syntaxes use a wildcard mask, which is a subnet mask with every bit flipped. A zero means "this bit must match" and a one means "ignore this bit".

subnet mask    255.255.255.192
wildcard mask    0.  0.  0. 63     255 minus each octet

Subtract each octet from 255 and you have it. The reason for the inversion is historical, and the practical consequence is that a wildcard does not have to be contiguous, so it can express things a subnet mask cannot, such as "every odd-numbered address".

Reading a mask you have been handed

Given 255.255.240.0, what do you have?

  1. Two full octets of 255 gives 16 bits, plus 240 which is four ones, so /20.
  2. Host bits are 32 minus 20 = 12, so 212 = 4,096 addresses, 4,094 usable.
  3. The interesting octet is the third, and 256 minus 240 = 16, so blocks start at x.x.0.0, x.x.16.0, x.x.32.0 and so on.

That is the entire procedure, and it is the same three steps for any mask you will ever be given.

Where to swim next