How to read this
Addresses use the documentation range 2001:db8::/32 (RFC 3849), link-local
fe80::/10, and the well-known multicast groups ff02::… — all safe
placeholders. Linux commands assume the modern iproute2 tools; the discovery
probes (rdisc6/ndisc6) come from the ndisc6 package.
- Link-scoped commands need a zone index — the
%eth0suffix (e.g.ping6 ff02::1%eth0) tells the kernel which interface to use. - Everything here is standard host behaviour — run it on a lab VM to watch the packets.
01Why IPv6 feels different
IPv4 leans on broadcast: ARP shouts "who has 10.0.0.1?" to everyone, and DHCP discovery floods the segment. IPv6 removes broadcast entirely. Its jobs are done by ICMPv6 messages sent to multicast groups, so only interested nodes process them. Three address types replace the old model:
- Unicast — one interface. Includes link-local
(
fe80::/10, auto-created on every interface, never routed off-link) and global unicast (2000::/3, internet-routable), plus ULA (fc00::/7, the private-address equivalent). - Multicast (
ff00::/8) — one-to-many; the workhorse for discovery. - Anycast — an address shared by several nodes; the nearest one answers.
There is no "broadcast" type at all — the closest thing is the all-nodes multicast group.
02Reading an IPv6 address
128 bits, written as eight 16-bit hex groups. A run of zero groups collapses to ::
(once per address), and leading zeros in a group are dropped. The first /64 is
almost always the network prefix; the last 64 bits are the
interface identifier (derived from the MAC via EUI-64, or randomized for privacy).
2001:0db8:acad:0001:0000:0000:0000:0010 # full form 2001:db8:acad:1::10 # same address, compressed └──────── prefix /64 ────────┘ └ interface ID ┘
IPv6 address = network prefix (/64) + interface identifier (64 bits)
03Multicast: the delivery backbone
Discovery works because a handful of well-known multicast groups exist on every link. A node joins the groups it cares about and listens; a sender targets a group instead of flooding everyone.
ff02::1 | All-nodes (link-local) — the closest thing to "broadcast". |
|---|---|
ff02::2 | All-routers — where hosts send Router Solicitations. |
ff02::1:ffXX:XXXX | Solicited-node — a per-address group used for address resolution & DAD. |
ff02::1:2 | All DHCPv6 servers & relay agents. |
ff02::fb / ff02::16 | mDNS / MLDv2 reports. |
The solicited-node group is the clever part: instead of asking every host, a node only needs to disturb the tiny set of neighbours whose address ends in the same 24 bits. Multicast also maps deterministically onto an Ethernet MAC, so NICs filter it in hardware.
solicited-node = ff02::1:ff00:0 + (last 24 bits of the target address)
multicast MAC = 33:33 + (last 32 bits of the IPv6 multicast address)
04ICMPv6 & Neighbor Discovery (NDP)
Neighbor Discovery Protocol (NDP) is a set of five ICMPv6 message types. Between them they replace ARP, ICMP router discovery, and ICMP redirects from the IPv4 world.
| Router Solicitation — RS (133) | Host → ff02::2: "any routers here? advertise now." |
|---|---|
| Router Advertisement — RA (134) | Router → ff02::1 (or unicast): prefix, flags, gateway, MTU. |
| Neighbor Solicitation — NS (135) | "Who owns this address?" (address resolution & DAD). |
| Neighbor Advertisement — NA (136) | "I do — here's my link-layer address." |
| Redirect (137) | Router hints a better next-hop for a destination. |
NDP = RS + RA + NS + NA + Redirect (all ICMPv6)
05Router discovery & SLAAC
When an interface comes up, the host sends a Router Solicitation to
ff02::2. Routers reply with a Router Advertisement (and also send RAs
periodically to ff02::1). The RA carries the on-link prefix, the
router as default gateway, the link MTU, and flags that decide how the
host gets addressed:
- A flag (per prefix, Autonomous) — use this prefix for SLAAC (build your own address).
- M flag (Managed) — get your address from DHCPv6 (stateful).
- O flag (Other) — get other config (DNS, NTP) from DHCPv6 (stateless).
With SLAAC, the host simply glues the advertised prefix to its own interface ID — no server, no lease. This is why an IPv6 host often gets a global address the instant it plugs in.
SLAAC address = RA prefix (/64) + interface ID
06Neighbor discovery — ARP's replacement
To send a packet to a neighbour, a host must map its IPv6 address to a MAC. Instead of an ARP broadcast, it sends a Neighbor Solicitation to the target's solicited-node multicast group. The owner answers with a Neighbor Advertisement containing its link-layer address, and both cache the result in the neighbour table (the IPv6 "ARP cache").
- DAD (Duplicate Address Detection) — before using a new address, the host sends an NS to that address. Any reply means it's already taken, so the address is abandoned.
- NUD (Neighbor Unreachability Detection) — entries move through
REACHABLE → STALE → PROBE → FAILED, so dead neighbours are noticed and re-resolved.
address resolution = NS (to solicited-node) + NA (with link-layer address)
07DHCPv6
DHCPv6 still exists — but the RA flags decide whether (and how) it's used. It runs over UDP
(client 546, server 547) and clients reach servers/relays at the
multicast group ff02::1:2. Two modes:
- Stateless DHCPv6 (RA O flag) — the host self-addresses with SLAAC and only asks DHCPv6 for extras like DNS servers and search domains.
- Stateful DHCPv6 (RA M flag) — the DHCPv6 server hands out the address itself and tracks the lease, like IPv4 DHCP. Clients are keyed by a DUID (not the MAC), and address requests use IA_NA options.
A crucial gotcha: classic DHCPv6 does not hand out a default gateway — the router is always learned from the RA. So even a "stateful DHCPv6" network still needs RAs for routing.
host config = RA (prefix + gateway) + [ SLAAC | DHCPv6 (M / O flags) ]
08See it on Linux
Watch every step above on a real interface with iproute2 and the ndisc6 tools.
ip -6 addr show dev eth0 # link-local (fe80) + any global/SLAAC addresses ip -6 route show # on-link prefixes + default via a link-local gateway (from RA) ip -6 neigh show # the neighbour table — IPv6's "ARP" cache, with NUD states ping6 -c2 ff02::1%eth0 # ping all-nodes on the link (neighbours reply, some as DUP!) rdisc6 eth0 # send a Router Solicitation, print the RA (prefix + flags) ndisc6 2001:db8:acad:1::1 eth0 # send a Neighbor Solicitation, print the target's MAC sysctl net.ipv6.conf.eth0.accept_ra # 1 = honour RAs (host); routers set forwarding=1 instead tcpdump -ni eth0 icmp6 # watch RS/RA/NS/NA fly by
$ ip -6 addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
inet6 2001:db8:acad:1:5054:ff:fe12:3456/64 scope global dynamic mngtmpaddr
valid_lft 86390sec preferred_lft 14390sec
inet6 fe80::5054:ff:fe12:3456/64 scope link
valid_lft forever preferred_lft forever
$ ip -6 neigh show fe80::1 dev eth0 lladdr 52:54:00:aa:bb:01 router REACHABLE 2001:db8:acad:1::10 dev eth0 lladdr 52:54:00:aa:bb:0a STALE
$ rdisc6 eth0 Soliciting ff02::2 (ff02::2) on eth0... Hop limit : 64 Stateful address conf. : No (RA M flag) Stateful other conf. : Yes (RA O flag) Prefix : 2001:db8:acad:1::/64 On-link : Yes Autonomous address conf. : Yes (SLAAC) from fe80::1
$ tcpdump -ni eth0 icmp6 IP6 fe80::5054:ff:fe12:3456 > ff02::2: ICMP6, router solicitation IP6 fe80::1 > ff02::1: ICMP6, router advertisement IP6 fe80::5054:ff:fe12:3456 > ff02::1:ff00:10: ICMP6, neighbor solicitation, who has 2001:db8:acad:1::10 IP6 2001:db8:acad:1::10 > fe80::5054:ff:fe12:3456: ICMP6, neighbor advertisement, tgt is 2001:db8:acad:1::10
09Where to go next
That's the whole loop: a host multicasts to find the router (RS/RA), self-addresses (SLAAC) or leases one (DHCPv6), and resolves neighbours with NS/NA instead of ARP — all over ICMPv6, no broadcast in sight. Sharpen the surrounding CLI with the Linux commands guide (its Connectivity & DNS and Sockets sections), or head back to the Knowledge Base.