In the previous post I explained that network prefixes in IPv6 are nearly always a fixed 64 bits in length, with a few exceptions. Strictly speaking, it’s actually the interface ID that’s fixed at 64 bits, which means that because IPv6 addresses are 128 bits long the network prefix has to be 64 bits too. The reason for this is to meet the needs of address auto-configuration, which is a new feature of IPv6 that supports:
- link-local address auto-configuration (so-called plug-and-play)
- stateless address auto-configuration (SLAAC, for global addresses)
Link-local addressing is pretty fundamental to IPv6. It enables a host to communicate with other nodes on the same network without the need for manual configuration or a DHCP server. The process is as follows:
- In the conventional method the host generates a 64-bit identifier for the interface by taking its 48-bit MAC address and inserting the string fffe into the middle. Then it “flips” bit 7 of the address from 0 to 1, so that the MAC address:
generates the interface ID:
This is what’s known as a Modified EUI-64 identifier (there are other methods but I will cover those in a later post).
- The host prefixes this identifier with the link-local network prefix fe80::/64, so that our example MAC address generates the link-local address:
- The host then tests this address for uniqueness on the local subnet by sending a Neighbor Solicitation message (ICMPv6 type 135) to the generated address. If it gets a Neighbor Advertisement message (ICMPv6 type 136) in reply then the process halts.
- If there is no response then the link-local address is assigned to the interface.
You can find more detail on this at Packetlife.
Once the link-local address is configured, the host sends a Router Solicitation message (ICMPv6 type 133) to the All Local Routers multicast address ff02::2. If there’s a local IPv6 router it will respond with a Router Advertisement message (ICMPv6 type 134). If that tells the host that it should auto-configure a global address then:
- The host will take the 64-bit global prefix advertised by the router and combine it with the 64-bit interface identifier previously generated to create a global address, so if the prefix is:
then our example interface ID generates the global address:
- It will test for uniqueness on the local subnet as for the link-local address
- If there is no response then the global address is assigned to the interface.
The whole set of messages and processes, together with other ancilliary messages and processes, is known as Neighbor Discovery. In principle other methods of global addressing (manual, DHCP) could use a variable-length prefix. However the address architecture RFC (RFC 4291) stipulates a 64-bit interface ID regardless of the configuration method. RFC 5375 warns against straying from the /64 prefix:
Using a subnet prefix length other than a /64 will break many features of IPv6, including Neighbor Discovery (ND), Secure Neighbor Discovery (SEND) [RFC3971], privacy extensions [RFC4941], parts of Mobile IPv6 [RFC4866], Protocol Independent Multicast – Sparse Mode (PIM-SM) with Embedded-RP [RFC3956], and Site Multihoming by IPv6 Intermediation (SHIM6) [SHIM6], among others.
In fact it’s specifically the SLAAC component of Neighbor Discovery that would be broken by a global network prefix other than /64, because of the way that the interface ID is generated.
In the next post, I’ll delve more into the background of SLAAC.
Finally I get an explanation on this /64 limitation! My ISP provides me only a /64 global prefix and I couldn’t understand why that’s not enough, and why abore that it goes to /60 and /56.
I don’t use VLAN at home so in theory I’d be fine with a /64 subnet, but I’d like OpenWRT/dhcpv6 to support shorter subnets anyway.
My trouble in this regard is that I can’t find out how to set a routed modem’s DHCPv6 server to delegate its global prefix to another router’s DHCPv6 on its subnet, so that this second router’s DHCPv6 server can attribute GUA and ULA addresses to its LAN.
What I’m doing on OpenWRT is set a short ULA prefix (something like fbcd::, I don’t remember the code) and then short suffixes to all devices equal to their last IPv4 address octet (::51). This way a device with IPv4 192.168.1.51 gets a (fixed!) ULA fbcd::51 and a global 2008:abcd:ef12:3456::51.