IP Services

DHCPv6 Explained: Stateful, Stateless, SLAAC, and the Relay

Cisco IOS XE show ipv6 dhcp binding with client DUID, IA_NA and an assigned address
In: IP Services, IPv6, Labs

IPv6 host addressing is where a lot of otherwise competent engineers quietly lose confidence, because there are three mechanisms that can all be running at once, they interact through two obscure flag bits in a router advertisement, and a host can end up with several addresses from different sources simultaneously. That is not a bug. It is the design.

This article untangles SLAAC, stateless DHCPv6, and stateful DHCPv6, shows the M and O flags that arbitrate between them, and builds a working stateful server with a relay on Cisco IOS XE, with a real Linux client acquiring a real lease. It extends the IPv6 cluster guide and the IP Services cluster guide.

Start Here: IPv6 Hosts Do Not Need DHCP

In IPv4, a host with no DHCP server has no address. Full stop. That assumption is baked so deeply into most engineers' instincts that IPv6's model feels wrong at first.

In IPv6, the router is the primary source of addressing information, not a server. A router periodically multicasts a Router Advertisement (RA) containing the on-link prefix, and any host that hears it can build itself a working global address without asking anyone. That is SLAAC (Stateless Address Autoconfiguration), and it is the default behaviour of essentially every IPv6 host on earth.

You can watch it happen. Here is a Linux host in the lab that has been given no DHCP configuration whatsoever, moments after being connected:

$ ip -br addr show eth0
eth0@if49   UP   10.0.10.100/24 2001:db8:10:0:5054:ff:fe79:35a2/64 fe80::5054:ff:fe79:35a2/64

The IPv4 address was configured manually. The IPv6 global address 2001:db8:10:0:5054:ff:fe79:35a2/64 appeared on its own, because the router advertised the prefix 2001:db8:10::/64 and the host did the rest.

Look at the interface identifier: 5054:ff:fe79:35a2. That ff:fe in the middle is the signature of EUI-64: the host took its 48-bit MAC address (52:54:00:79:35:a2), split it in half, jammed ff:fe into the gap, and flipped the seventh bit. If you see ff:fe in an IPv6 address, you are looking at an EUI-64 SLAAC address and you can read the MAC straight out of it. (Which is exactly why RFC 4941 privacy addresses exist, and why most desktop OSes now use random identifiers instead by default.)

The Two Flags That Decide Everything

The RA carries two bits that tell the host what else to do. Getting these right is the whole game.

M flag (Managed)"Get your address from DHCPv6." Set it, and the host asks a DHCPv6 server for an address instead of building one.
O flag (Other)"Get your other config (DNS, domain) from DHCPv6." The address still comes from SLAAC.

Those two bits produce the three deployment models, and the names finally make sense:

Pure SLAAC
M / O0 / 0
Address from the RA prefix. DNS from the RA (RDNSS option), if the router sends it. No DHCPv6 at all.
Stateless DHCPv6
M / O0 / 1
Address from SLAAC. DNS and domain from a DHCPv6 server. The server keeps no lease state, hence "stateless".
Stateful DHCPv6
M / O1 / 1
Address AND config from the server, which tracks every lease. The closest thing to IPv4 DHCP.

"Stateless" and "stateful" refer to the server's state, not the client's. A stateless DHCPv6 server hands out DNS servers and forgets you exist. A stateful one records who has which address, which is what you need if you want to answer "which machine was 2001:db8::42 last Tuesday."

One critical subtlety: setting the M flag does not automatically stop SLAAC. If the RA still carries a prefix with the autonomous flag set, a host will build a SLAAC address and ask DHCPv6 for one, and end up with both. If you want DHCPv6 to be the only source, you must explicitly tell the router to stop advertising the prefix as autoconfigurable.

Building Stateful DHCPv6 with a Relay

The lab: a client on the 2001:db8:10::/64 LAN behind R1, and the DHCPv6 server on R2, one hop away. This is the realistic topology, because your DHCP server is essentially never on the same segment as your clients.

The server (R2)

R2(config)# ipv6 dhcp pool PINGLABZ-STATEFUL
R2(config-dhcpv6)#  address prefix 2001:DB8:10:AAAA::/64 lifetime 3600 1800
R2(config-dhcpv6)#  dns-server 2001:4860:4860::8888
R2(config-dhcpv6)#  domain-name pinglabz.local
!
R2(config)# interface Ethernet0/1
R2(config-if)#  ipv6 dhcp server PINGLABZ-STATEFUL

The two lifetimes are valid (3600) and preferred (1800), in that order. An address past its preferred lifetime is "deprecated": still usable for existing connections, but not chosen for new ones. Past the valid lifetime it is gone. This graceful two-stage expiry has no IPv4 equivalent and is one of the genuinely nice parts of IPv6.

The relay and the flags (R1)

R1(config)# interface Ethernet0/2
R1(config-if)#  ipv6 nd managed-config-flag
R1(config-if)#  ipv6 nd other-config-flag
R1(config-if)#  ipv6 nd prefix 2001:DB8:10::/64 no-autoconfig
R1(config-if)#  ipv6 dhcp relay destination 2001:DB8:12::2 Ethernet0/1

Four lines, four distinct jobs:

  • managed-config-flag sets M. Hosts will now solicit an address from DHCPv6.
  • other-config-flag sets O. Hosts will take DNS and domain from DHCPv6 too.
  • prefix ... no-autoconfig clears the autonomous bit on the advertised prefix. This is the line everyone forgets. Without it, hosts keep building SLAAC addresses alongside their DHCPv6 lease, and you have two addresses per host and no idea which one traffic will use.
  • ipv6 dhcp relay destination forwards the client's solicit (sent to the link-local multicast group ff02::1:2, which does not route) onward to the actual server as unicast.

The Exchange

DHCPv6 uses four messages, and if you know DHCPv4's DORA they map cleanly:

SOLICIT (client)"Are there any DHCPv6 servers?" Sent to ff02::1:2. The DISCOVER equivalent.
ADVERTISE (server)"I am here and I can offer you this." The OFFER equivalent.
REQUEST (client)"I will take it." The REQUEST equivalent.
REPLY (server)"It is yours, here are the lifetimes." The ACK equivalent.

The client in the lab is a Linux host running udhcpc6. Here it is doing exactly that:

$ udhcpc6 -i eth0
udhcpc6: started, v1.36.1
udhcpc6: sending discover
udhcpc6: sending discover
udhcpc6: sending select
udhcpc6: IPv6 obtained, lease time 3600

Solicit, solicit (the first went unanswered while the relay warmed up), select, and a lease with the 3600-second lifetime configured on the server. The client is on one subnet, the server is on another, and the relay carried the conversation between them.

The Binding: What the Server Remembers

This is where "stateful" earns its name:

R2#show ipv6 dhcp binding
Client: FE80::5054:FF:FE79:35A2
  DUID: 000300015254007935A2
  Username : unassigned
  VRF : default
  IA NA: IA ID 0x8FFD7C11, T1 900, T2 1440
    Address: 2001:DB8:10:AAAA:31E0:5957:EFD4:7F52
            preferred lifetime 1800, valid lifetime 3600
            expires at Jul 12 2026 01:54 AM (3587 seconds)

Several things worth reading properly:

  • DUID (DHCP Unique Identifier) is how DHCPv6 identifies a client, and it is not the MAC address. It is generated once by the client and persists across reboots and NIC changes. This breaks every IPv4 habit you have around MAC-based reservations. Here the DUID happens to embed the MAC (5254007935A2) because it is DUID type 3 (link-layer), but that is a client choice, not a guarantee.
  • IA_NA (Identity Association for Non-temporary Addresses) is the container for the leased address. A client can hold several.
  • T1 (900) and T2 (1440) are the renew and rebind timers, defaulting to 50% and 80% of the preferred lifetime. At T1 the client asks the same server to renew. At T2 it gives up on that server and asks any server.
  • The allocated address is 2001:DB8:10:AAAA:31E0:5957:EFD4:7F52. Note the host portion is random, not EUI-64. There is no ff:fe. That is the fingerprint of a DHCPv6-assigned address versus a SLAAC one, and it is the quickest way to tell at a glance which mechanism gave a host its address.
R2#show ipv6 dhcp pool
DHCPv6 pool: PINGLABZ-STATEFUL
  Address allocation prefix: 2001:DB8:10:AAAA::/64 valid 3600 preferred 1800 (1 in use, 0 conflicts)
  DNS server: 2001:4860:4860::8888
  Domain name: pinglabz.local
  Active clients: 1

DHCPv6-PD, Briefly

One more mode exists and it has no IPv4 analogue at all. Prefix Delegation hands a client an entire prefix (a /56 or /48) rather than a single address, so the client can subnet it and hand addresses to devices behind it.

This is how your home router gets IPv6 from your ISP: it does not receive one address, it receives a /56, and it then advertises /64s from that block onto your home LANs. Configured with prefix-delegation pool on the server side and ipv6 dhcp client pd on the client interface. It is the standard model for any downstream router, not just consumer kit.

When It Does Not Work

Host has a SLAAC address AND a DHCPv6 oneYou set M but left the prefix autonomous. Add ipv6 nd prefix ... no-autoconfig.
Host gets no address at allIs ipv6 unicast-routing on? Without it the router sends no RAs and the host has nothing to react to.
Solicits never reach the serverMissing relay. ff02::1:2 is link-local and does not route. show ipv6 dhcp interface on both ends.
Reservation by MAC does not workDHCPv6 keys on DUID, not MAC. Reserve by DUID.

And a security note: an RA is unauthenticated, and any host on the segment can send one. A rogue RA (malicious or, far more commonly, a misconfigured Windows box with sharing enabled) will reconfigure every host on the VLAN. The defence is RA Guard on the access switch, which belongs to the IPv6 first-hop security toolkit.

FAQ

Which should I use?

Stateful DHCPv6 if you need to know which device had which address (most enterprises, for audit and forensics). SLAAC plus stateless DHCPv6 if you just need working hosts and DNS with minimal infrastructure. Pure SLAAC for simple or transit segments.

Can a host get DNS without any DHCPv6 at all?

Yes. The RDNSS option in the RA (RFC 8106) carries DNS servers directly. Modern OSes support it; some older ones ignore it, which is why stateless DHCPv6 still exists.

Why is my client's address not EUI-64 even with SLAAC?

Privacy extensions (RFC 4941). Most desktop OSes generate random, rotating interface identifiers by default rather than embedding the MAC. This is a feature.

Does DHCPv6 give out a default gateway?

No, and this surprises people. There is no gateway option in DHCPv6. The default route always comes from the Router Advertisement. You cannot run DHCPv6 without RAs.

What is T1 and T2?

Renew (T1) and rebind (T2) timers, defaulting to 50% and 80% of the preferred lifetime. At T1 the client renews with the same server; at T2 it broadcasts for any server.

Key Takeaways

  • IPv6 hosts get addresses from Router Advertisements by default. DHCPv6 is optional, and layered on top.
  • The M flag means "get your address from DHCPv6." The O flag means "get your other config from DHCPv6." Those two bits define all three models.
  • Setting M does not stop SLAAC. You must also set ipv6 nd prefix ... no-autoconfig, or hosts end up with two addresses.
  • An ff:fe in the middle of the host portion means EUI-64 SLAAC. A random host portion means DHCPv6 assigned it. You can diagnose the mechanism from the address alone.
  • DHCPv6 identifies clients by DUID, not MAC. Every MAC-based reservation habit you have from IPv4 is wrong here.
  • DHCPv6 never provides a default gateway. The default route always comes from the RA.
  • Solicits go to ff02::1:2, which is link-local. Off-segment servers require a relay.

Next: the IPv6 cluster guide, or the IP Services cluster guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.