The /31 Subnet Nobody Taught You, and Why It Works
Every subnetting class teaches the same formula: 2 to the power of the host bits, minus 2. Plug in a /31 subnet and you get 2¹ − 2 = 0 usable hosts. By that math, a /31 is useless.
Your router disagrees. A /31 carries a working link between two devices, and it has been a standards-track IETF practice since RFC 3021 in December 2000.
So here's the short answer: on a point-to-point link, a /31 has two usable addresses, both of them, with no network address and no broadcast address. Below you'll get where the "minus 2" rule came from, what the RFC changed, real config for Linux, Cisco, and Junos, the code bug that /31s expose, and when I'd still reach for a /30. My take: for router-to-router links, /31 should be your default.
How many usable hosts does a /31 subnet have?
Two. A /31 leaves one host bit, so it holds exactly two addresses. RFC 3021 says that on a point-to-point link with a 31-bit mask, those two addresses "MUST be interpreted as host addresses."
Here's how the three smallest prefixes compare, using addresses from 10.0.0.0:
| Prefix | Mask | Addresses | Usable | Network address | Broadcast address |
|---|---|---|---|---|---|
| /30 | 255.255.255.252 | 4 (10.0.0.0–.3) | 2 (.1 and .2) | 10.0.0.0 | 10.0.0.3 |
| /31 | 255.255.255.254 | 2 (10.0.0.0–.1) | 2 (.0 and .1) | none | none |
| /32 | 255.255.255.255 | 1 (10.0.0.0) | 1 | none | none |
Notice the /30 and the /31 give you the same two usable addresses per link. The /31 just stops paying for two addresses nobody uses.
Python agrees. On Python 3.13.5, list(ip_network('10.0.0.0/31').hosts()) returns both 10.0.0.0 and 10.0.0.1, and the ipaddress docs spell out that for a mask length of 31, "the network address and network broadcast address are also included in the result."
Where the "minus 2" rule came from
The rule wasn't made up by certification authors. It's in the standards.
RFC 950 (1985) set up subnetting and carried forward an older convention: an address field of all zeros means "this network," and all ones means "all hosts." RFC 1122 (1989), the big requirements document for internet hosts, made it strict. Section 3.2.1.3 says addresses "are not permitted to have the value 0 or -1" (all ones) in the host field, and then draws the conclusion: "This implies that each of these fields will be at least two bits long."
Two host bits is a /30. So for over a decade, a /30 was the smallest legal subnet with real hosts in it, and every textbook table stopped there.
The funny part is that RFC 950 itself only required the host field to be "at least 1-bit wide." RFC 3021 points to that line and says the older document "has already hinted at the possible use of a 1-bit wide host-number field." The door was open. The broadcast and network conventions just kept anyone from walking through it.
What RFC 3021 actually changed
The argument in RFC 3021 is short and hard to argue with. A point-to-point link has exactly two ends. It doesn't "support the notion of broadcast," because anything one end sends always reaches the other. So reserving a network address and a broadcast address on that link wastes half of a /30.
The RFC didn't just declare /31 fine. It rewrote specific rules in RFC 1122 and in RFC 1812, the router requirements, so the all-zeros and all-ones addresses can be used as source addresses when "the originator is one of the endpoints of a point-to-point link with a 31-bit mask." Routers must treat packets to either address on such a link as addressed to the router itself, not as a broadcast.
Two practical consequences:
- Broadcast still works, one kind of it. The limited broadcast, 255.255.255.255, "MUST be used for all broadcast traffic" on a /31 link.
- Directed broadcast is gone, and that's a feature. You can't send a broadcast to a /31 from a remote network. The RFC counts that as a small security win against Smurf-style attacks, which bounce directed broadcasts off a network to flood a victim.
What about routing protocols? The RFC's authors reported that the change had been tested by "at least three ISPs" with no problems, including OSPF, IS-IS, BGP, and EIGRP. Those protocols talk to neighbors with multicast, limited broadcast, or unicast, and none of those care about a missing subnet broadcast.
The savings, in actual numbers
Halving sounds abstract until you count links. RFC 3021 gives its own example: a network with 500 point-to-point links uses 2,000 addresses with /30s and 1,000 with /31s. That's 1,000 addresses back, or four old class C blocks.
Or look at it from the other side. Carve one /24 into point-to-point links:
| Carved into | Links you get | Addresses per link |
|---|---|---|
| /30 | 64 | 4 |
| /31 | 128 | 2 |
Same block, twice the links. If you're numbering a data center fabric or an ISP backbone out of public IPv4 space, that's real money. If you're on private 10.x space, the addresses are cheap, but you still get a tidier plan: every link is "even address on one side, odd address on the other."
How to configure a /31 on Linux, Cisco, and Junos
The rule for picking addresses: a /31 always starts on an even number. 10.0.0.0/31 holds .0 and .1; 10.0.0.2/31 holds .2 and .3. Give the even address to one end and the odd one to the other.
Linux. I tested this on kernel 6.12 with iproute2 6.15, using a veth pair (a virtual cable with two ends):
ip addr add 10.0.0.0/31 dev v0
ip addr add 10.0.0.1/31 dev v1
The interesting part is what the kernel didn't do. For a /30 on the same interface, it added a broadcast route automatically (broadcast 10.0.1.3 in ip route show table local). For the /31, it added no broadcast route at all. The kernel treats both addresses as hosts, which is exactly what RFC 3021 asks for.
Cisco IOS and IOS XE. Cisco's IOS XE 17 addressing guide has a whole task for this, with this example:
interface serial0/0
no shutdown
ip address 192.168.100.2 255.255.255.254
The same guide lists the feature as arriving in IOS 12.0(14)S and 12.2(4)T, and it asks for ip classless, which it notes is on by default in many versions. One catch: that task is written for point-to-point (non-multiaccess) WAN interfaces. If you're doing this on Ethernet, check the docs for your platform and release.
Junos. Juniper's interface address docs say its routers and switches "support /31 destination prefixes when used in point-to-point Ethernet configurations." You set it with the normal family inet address statement:
set interfaces ge-0/0/0 unit 0 family inet address 10.0.0.0/31
Then verify. On Linux, ip route showed 10.0.0.0/31 dev v0 proto kernel scope link src 10.0.0.0, a normal connected route with no broadcast entry beside it.
Where a /31 bites you
The protocol side has been settled for decades. The trouble shows up at the edges.
More than two devices on the segment. RFC 3021 covers point-to-point links only and says plainly that effects "on other types of interfaces are not considered." If a switch port might someday get a third device, or a pair of routers shares a VLAN with a monitoring box, a /31 has no room for it.
One end doesn't support it. The RFC warns that a link "in which only one end supports the use of 31-bit prefixes may not operate correctly." Juniper's note goes further: /31 is "not supported by many other devices, such as hosts, hubs, routers, or switches," so you have to check the peer before you configure. Your carrier's handoff box or an old appliance is the usual suspect.
Your own code. This is the one that surprised me. Plenty of scripts find usable hosts by excluding the network and broadcast addresses. In Python's ipaddress, a /31 still reports a network_address of 10.0.0.0 and a broadcast_address of 10.0.0.1, because those attributes are pure arithmetic. So this innocent-looking filter returns an empty list:
n = ip_network('10.0.0.0/31')
[h for h in n.hosts() if h not in (n.network_address, n.broadcast_address)]
# []
Use hosts() on its own and trust it. The same goes for any spreadsheet or IPAM export that hardcodes 2^n - 2: it will report zero usable addresses for every /31 you own.
Odd starting addresses. ip_network('10.0.0.1/31') raises ValueError: 10.0.0.1/31 has host bits set. That's a correct complaint. 10.0.0.1 is a fine interface address on the 10.0.0.0/31 link, but it isn't a network you can name. If your automation builds link names from the interface IP, mask it first (Python's ip_interface('10.0.0.1/31').network does that).
IPv6 got the same idea: /127
IPv6 has no broadcast addresses at all. RFC 4291 says so outright. You'd think that made the problem disappear. For years, /127 was actively discouraged: RFC 3627 (2003) called it "Considered Harmful" because it clashed with a special anycast address, and operators were pushed toward a /64 even on a two-router link.
RFC 6164 (2011) reversed that for inter-router links. It describes the IPv6 /127 as a practice that "parallels the use of 31-bit prefixes in IPv4," and its reasons are about security, not saving space. With a /64 on a link, an attacker can send packets to the 2^64 − 3 unused addresses and make a router fill its neighbor cache with entries that will never resolve. A /127 "eliminates it completely," because there are only two addresses and both are in use.
RFC 6164 says routers "MUST support" /127 on point-to-point inter-router links and must disable the Subnet-Router anycast address for that prefix. It also asks you not to assign addresses whose last 64 bits are all zeros, so you don't collide with that anycast address. It also reserves the top 128 values of those last 64 bits for other anycast uses. If you number links out of one /64, skip the first /127 and the last few.
When I'd still use a /30
I'd make /31 the default on any link that is truly point-to-point and where I control both ends. That covers most router-to-router links in a modern network.
I'd still use a /30 when:
- the far end is a device I can't check or don't control, and its docs don't mention /31,
- the "link" is a VLAN that might grow a third member,
- or some tool in my pipeline (monitoring, IPAM, a firewall rule generator) still does
2^n - 2and I can't fix it this week.
None of those is about the /31 being wrong. They're about the rest of your stack catching up to a standard from 2000.
Want to check a block before you carve it? The CyberScryb subnet calculator runs in your browser and counts a /31 as 2 usable hosts, listing both addresses as the usable range. It still fills in its network and broadcast tiles for every prefix, so for a /31, read the usable range and ignore those two. If you like small browser tools for this kind of work, there's a roundup in the free developer tools guide. And if old numeric assumptions baked into code are your thing, the Year 2038 problem is the same story with timestamps.
FAQ
Can I use a /31 on an Ethernet link?
Often, yes, if both ends are routers configured as a point-to-point pair. Juniper documents /31 on point-to-point Ethernet, and Linux handled it fine on the virtual Ethernet pair I tested. Cisco's IOS XE guide describes the task for non-multiaccess WAN interfaces, so check your platform's docs before relying on it.
Does OSPF or BGP work over a /31?
Yes. RFC 3021 says 31-bit prefixes have "no impact on current routing protocols," and its authors reported successful tests with OSPF, IS-IS, BGP, and EIGRP.
What's a /32 for, then?
A /32 is one address with no peer. You'll see it on loopback interfaces and in routes or firewall rules that point at a single host. Python's hosts() returns that one address for a /32.
The two addresses were always there
The "minus 2" rule was never wrong, just incomplete. It describes networks with many hosts and a broadcast domain. A point-to-point link has neither, and the standards have said so for over 25 years.
Your next step: search your scripts and spreadsheets for - 2, run one /31 through them, and see whether they say 2 or 0.