DHCPv6 prefix delegation
Static handovers are fine for your own routers. For routers you don't manage (customers, branch offices, a home router behind yours), IPv6 has a standard way to hand out prefixes automatically: DHCPv6 prefix delegation (DHCPv6-PD). It's exactly what your ISP's equipment does when your home router "gets a /56".
- On R1, a DHCPv6 server on the transit link with a pool of prefixes to delegate: 2001:db8:1000:200::/55, split into /56s, so two downstream routers can get one each.
- On R2, a DHCPv6 client on its upstream interface asking for a /56, and instructions for using it: take /64 number 0 (
sla-id 0) from whatever arrives, put it on eth1, and use::1in that /64 as R2's address. The RA on LAN2 usesprefix ::/64, meaning "advertise whatever prefixes this interface has", because R2 doesn't know its prefix in advance.
After a few seconds, R1's lease table shows 2001:db8:1000:200::/56 delegated to R2, identified by its DHCP Unique Identifier (DUID). R2 has numbered LAN2 from it, and client2 has picked up a second address via SLAAC. Best of all, R1 installed a route for the delegated /56 by itself, pointing at R2's link-local address. With a static handover, forgetting that route was the classic mistake; with PD, the router doing the delegating takes care of it.
What PD doesn't do: the blackhole
R2 uses one /64 of its delegated /56. Send traffic to an unused part of it (2001:db8:1000:2ff::1 here) and it loops: R2 has no route for it, so it follows R2's default route back to R1, R1 sends it back to R2 because of the delegation route, and so on until the hop limit expires. The traceroute shows the two routers taking turns.
The static /56 doesn't have this problem, because R2 has a blackhole for it: traffic to unused space is dropped at R2. With PD, R2 doesn't know its prefix until it gets a lease. In practice, delegations usually stay the same, because DHCPv6 servers normally keep giving the same prefix to the same DUID. Once you know your prefix, add the blackhole.
A lab note: DUIDs and virtual machines
On the first attempt in this lab, R2's DHCPv6 client wouldn't start (DUID file corrupted). VyOS builds the DUID from the machine's hardware UUID, and the lab's QEMU virtual machines didn't have one. Real hardware and normal hypervisors always do. The lab's start script now gives each VM a UUID. If you build your own VyOS VMs, do the same.
set service dhcpv6-server shared-network-name TRANSIT interface 'eth2'
set service dhcpv6-server shared-network-name TRANSIT subnet 2001:db8:1000:ff::/64 subnet-id '1'
set service dhcpv6-server shared-network-name TRANSIT subnet 2001:db8:1000:ff::/64 prefix-delegation prefix 2001:db8:1000:200:: prefix-length '55'
set service dhcpv6-server shared-network-name TRANSIT subnet 2001:db8:1000:ff::/64 prefix-delegation prefix 2001:db8:1000:200:: delegated-length '56'- Line 1: Serve DHCPv6 on eth2.
- Line 2: The transit subnet the requests arrive on.
- Line 3: The pool: 2001:db8:1000:200::/55…
- Line 4: …handed out in /56s.
set interfaces ethernet eth0 dhcpv6-options pd 0 length '56'
set interfaces ethernet eth0 dhcpv6-options pd 0 interface eth1 address '1'
set interfaces ethernet eth0 dhcpv6-options pd 0 interface eth1 sla-id '0'
set service router-advert interface eth1 prefix ::/64- Line 1: Request a /56 on the upstream interface.
- Lines 2–3: Put /64 number 0 of it on eth1, with ::1 as R2's address.
- Line 4: Advertise whatever prefixes eth1 has.
vyos@R1:~$ show dhcpv6 server leases
IPv6 address MAC address State Last communication Lease expiration Remaining Pool Hostname Type DUID
---------------------- ------------- ------- -------------------- ------------------- ----------- ------- ---------- ------ -----------------------------------------------------
2001:db8:1000:200::/56 - active 2026-10-17 01:11:47 2026-10-17 03:11:47 1:59:50 TRANSIT - IA_PD 00:04:00:00:00:00:00:00:40:00:80:00:00:00:00:00:00:02
vyos@R1:~$ show ipv6 route 2001:db8:1000:200::1
Routing entry for 2001:db8:1000:200::/56
Known via "kernel", distance 0, metric 1024, best
Last update 00:00:10 ago
Flags: Selected
Status: Installed
* fe80::5054:ff:fe02:1, via eth2, weight 1- Line 4: The /56 delegated to R2, identified by its DUID in the last column (scroll right).
- Line 7: A kernel route, installed when the prefix was delegated…
- Line 11: …via R2's link-local address on the transit link.
vyos@R2:~$ show interfaces ethernet eth1 brief
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface IP Address S/L Description
--------- ---------- --- -----------
eth1 2001:db8:1000:200::1/64 u/u LAN2
2001:db8:1000:100::1/64
vyos@R2:~$ show ipv6 route 2001:db8:1000:200::/56
% Network not in table- Line 5: The delegated /64, ::1, on LAN2 (alongside the static one).
- Line 8: No blackhole for the delegated /56.
root@client2:~# ip -6 addr show dev eth0 scope global
2: eth0@if606: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link-netnsid 0
inet6 2001:db8:1000:200:e41b:1ff:fef2:b011/64 scope global dynamic mngtmpaddr
valid_lft 2591997sec preferred_lft 14397sec
inet6 2001:db8:1000:100:e41b:1ff:fef2:b011/64 scope global dynamic mngtmpaddr
valid_lft 2591997sec preferred_lft 14397sec
root@client2:~# ping -6 -c 2 -I 2001:db8:1000:200:e41b:1ff:fef2:b011 2001:db8:f000::10
PING 2001:db8:f000::10(2001:db8:f000::10) from 2001:db8:1000:200:e41b:1ff:fef2:b011 : 56 data bytes
64 bytes from 2001:db8:f000::10: icmp_seq=1 ttl=61 time=3.86 ms
64 bytes from 2001:db8:f000::10: icmp_seq=2 ttl=61 time=4.28 ms
--- 2001:db8:f000::10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1007ms
rtt min/avg/max/mdev = 3.855/4.067/4.280/0.212 ms- Lines 3–4: From the delegated prefix.
- Lines 7–10: And it works.
root@server:~# traceroute -6 -n -q 1 -m 8 2001:db8:1000:2ff::1
traceroute to 2001:db8:1000:2ff::1 (2001:db8:1000:2ff::1), 8 hops max, 80 byte packets
1 2001:db8:f000::1 0.111 ms
2 2001:db8:ffff:1::2 3.092 ms
3 2001:db8:1000:ff::2 6.224 ms
4 2001:db8:1000:ff::1 6.605 ms
5 2001:db8:1000:ff::2 7.721 ms
6 2001:db8:1000:ff::1 8.052 ms
7 2001:db8:1000:ff::2 8.383 ms
8 2001:db8:1000:ff::1 8.459 ms
root@server:~# traceroute -6 -n -q 1 -m 8 2001:db8:1000:1ff::1
traceroute to 2001:db8:1000:1ff::1 (2001:db8:1000:1ff::1), 8 hops max, 80 byte packets
1 2001:db8:f000::1 0.115 ms
2 2001:db8:ffff:1::2 0.799 ms
3 *
4 *
5 *
6 *
7 *
8 *- Lines 5–10: Inside the delegated /56, with no blackhole on R2: R2 and R1 bounce it between them.
- Lines 11–20: Inside the static /56: R2's blackhole drops it, silently.
Check your understanding
With DHCPv6-PD, who installs the route for the delegated prefix on the delegating router?
- Nobody; you must add it by hand
- The delegating router, when it hands out the prefix
- The downstream router, by advertising it in an RA
- The ISP