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 %eth0 suffix (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::1All-nodes (link-local) — the closest thing to "broadcast".
ff02::2All-routers — where hosts send Router Solicitations.
ff02::1:ffXX:XXXXSolicited-node — a per-address group used for address resolution & DAD.
ff02::1:2All DHCPv6 servers & relay agents.
ff02::fb / ff02::16mDNS / 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.