Skip to main content
RunBook Academy

VyOSXI · IPv6IPv6

IPv6 fundamentals — 128-bit addressing, headers, ICMPv6, NDP

Foundation⏱ ~18 minshow ipv6ip -6 addr showip -6 neigh showping6tcpdumpvyos

What you'll learn

  • Explain why IPv6 uses 128-bit addresses and a simplified 40-byte header
  • Describe the ICMPv6 role that subsumes ARP, router discovery, redirect, and PMTUD
  • Identify link-local addresses (fe80::/10) and how EUI-64 builds an interface identifier from a MAC
  • Read the IPv6 header and the most common extension headers in a packet capture

Prerequisites

Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15

Not yet marked complete on this device.

IPv6 fundamentals — 128-bit addressing, headers, ICMPv6, NDP

IPv6 is not IPv4 with longer addresses. It is a redesign that takes the lessons of thirty years of IPv4 and bakes them into the protocol. The header is fixed at 40 bytes and fit into the minimum Ethernet MTU. ARP is gone; ICMPv6 takes its place alongside router discovery and redirect. Address assignment is intended to be stateless. The broadcast address disappears and is replaced with a structured multicast architecture.

A production routing engineer who treats IPv6 as “just turn on another address family” gets surprised by every one of these differences. The lesson walks through them so the rest of Part XI — addressing, router advertisements, DHCPv6, routing, and troubleshooting — has a solid foundation to build on.

How an IPv4 packet differs from an IPv6 packet

flowchart LR
  subgraph V4["IPv4 header (20-60 bytes)"]
    V40[Version 4] --> V41[IHL]
    V41 --> V42[TOS / DSCP]
    V42 --> V43[Total Length]
    V43 --> V44[Identification]
    V44 --> V45[Flags + Fragment Offset]
    V45 --> V46[TTL]
    V46 --> V47[Protocol]
    V47 --> V48[Header Checksum]
    V48 --> V49[Src / Dst IPv4 32-bit]
  end
  subgraph V6["IPv6 header (fixed 40 bytes)"]
    V60[Version 6] --> V61[Traffic Class]
    V61 --> V62[Flow Label]
    V62 --> V63[Payload Length]
    V63 --> V64[Next Header]
    V64 --> V65[Hop Limit]
    V65 --> V66[Src / Dst IPv6 128-bit]
  end

The IPv4 header is variable-length because of options and the header checksum. The IPv6 header is fixed at 40 bytes. Options that were in the IPv4 header are now chained as extension headers behind the main header. There is no header checksum — the link layer and the transport layer (TCP, UDP) check their own integrity, and removing the checksum from the network header saves work on every hop.

Extension headers replace IPv4 options

flowchart LR
  M[Main IPv6 header<br/>Next Header = Routing] --> R[Routing header]
  R --> F[Fragment header]
  F --> D[Destination Options header]
  D --> P[Upper-layer payload<br/>TCP or UDP]

Extension headers are daisy-chained. Each one has its own “Next Header” field that names the next one. The chain ends at the upper-layer protocol. Routers along the path only inspect the main header and any Hop-by-Hop header; everything else is read only by the endpoints. This is why IPv6 forwarding is faster than IPv4 forwarding in many implementations.

The Fragment header is one of the most operationally important. IPv6 routers do not fragment transit packets — fragmentation is the sender’s responsibility, using a Path MTU Discovery mechanism the host runs. If a packet is too big for the path, the router sends an ICMPv6 Packet Too Big back to the source and drops the packet. Lesson vyos-xi-06-ipv6-troubleshoot covers PMTUD failures in detail.

ICMPv6 — three protocols in one

In IPv4, three separate protocols handle what ICMPv6 does alone:

  • ARP (Layer 2 / Layer 3 address resolution)
  • ICMP (router discovery redirects, unreachable, PMTUD)
  • IGMP (multicast group management)
flowchart TB
  subgraph ICMPv6[ICMPv6 - protocol number 58]
    ND[NDP<br/>type 135 / 136<br/>neighbor solicit / advertise]
    RA[Router Advertisement<br/>type 134]
    RS[Router Solicitation<br/>type 133]
    RED[Redirect<br/>type 137]
    TB[Packet Too Big<br/>type 2]
    U[Destination Unreachable<br/>type 1]
    MLD[MLD<br/>multicast listener discovery]
  end
  N[IPv6 Node] --> ND
  N --> RA
  N --> RS
  N --> RED
  N --> TB
  N --> U
  N --> MLD

NDP (Neighbor Discovery Protocol) replaces ARP. RA / RS replace the ICMPv4 Router Discovery messages that RFC 1256 added later and that IPv6 builds in from day one. MLD replaces IGMP. Every IPv6 control-plane protocol the operator relies on runs inside ICMPv6.

NDP replaces ARP

sequenceDiagram
  autonumber
  participant H as Host A<br/>fe80::1
  participant R as Router<br/>fe80::2
  participant N as Next-hop B<br/>2001:db8::1

  H->>R: RS (ICMPv6 type 133)<br/>multicast ff02::2
  R-->>H: RA (ICMPv6 type 134)<br/>prefix, lifetime, MTU
  Note over H: builds default route to R<br/>with link-local as next-hop
  H->>N: NS (ICMPv6 type 135)<br/>who has 2001:db8::1?<br/>solicited-node multicast ff02::1:ff00:1
  N-->>H: NA (ICMPv6 type 136)<br/>2001:db8::1 is at MAC
  Note over H: kernel caches NA in neighbour table

NDP runs over ICMPv6, which runs over IPv6. It uses solicited-node multicast instead of broadcast. When Host A wants the MAC for 2001:db8::1, the kernel computes ff02::1:ff00:0001 (the last 24 bits of the target address appended to ff02::1:ff), joins that multicast group on the interface, and sends the Neighbor Solicitation to that group. Only the host whose IPv6 ends in ::1 listens to that group, so the request is delivered without disturbing every host on the segment.

The Reply is unicast. The host installs the entry in the Linux neighbour cache, which ip -6 neigh show displays.

Every IPv6 interface that supports multicast automatically assigns itself a link-local address from fe80::/10. The interface identifier is built from the MAC using EUI-64 (or from a random number in modern kernels with addrgenmode=random).

vyos@vyos:~$ ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
    inet6 fe80::5054:ff:fe12:3456/64 scope link
    inet6 2001:db8::1/64 scope global

The scope link keyword on fe80::5054:ff:fe12:3456 is Linux’s way of saying “this address is valid only on this link”. Routers must not forward packets with link-local source or destination addresses. They are used for:

  • Neighbor Discovery (NS / NA)
  • Router Solicitation / Router Advertisement
  • Routing protocols (OSPFv3, BGP) on the wire — the TCP/UDP sessions use link-local source and destination

EUI-64 from a 48-bit MAC

flowchart LR
  A[48-bit MAC<br/>52:54:00:12:34:56] --> B[Insert FF:FE in the middle<br/>52:54:00 FF:FE 12:34:56]
  B --> C[Flip bit 6 of byte 0<br/>5250<br/>50:54:00:FF:FE:12:34:56]
  C --> D[Colon form<br/>50:54:00:ff:fe:12:34:56]
  D --> E[IPv6 form<br/>fe80::5054:ff:fe12:3456]

The conversion rule:

  1. Split the MAC in half: 52:54:00 and 12:34:56.
  2. Insert FF:FE in the middle.
  3. Flip the Universal/Local bit (bit 6, counting from 1) of the first byte. 52 binary is 01010010; flipping bit 6 gives 01000010 = 50.
  4. Combine: 50:54:00:FF:FE:12:34:56.
  5. Prepend fe80:: to get the link-local address.

This is how 52:54:00:12:34:56 becomes fe80::5054:ff:fe12:3456. The pattern is mechanically recognisable: every VyOS link-local address on a hypervisor VM ends in ff:fe followed by the last four bytes of the MAC.

Why IPv6 was redesigned

The IPv4 design problems IPv6 fixed:

  • Address exhaustion. 32 bits was a comfortable size in 1980. By 2010 the free pool was exhausted. 128 bits gives 3.4 × 10^38 addresses — enough to give every atom on the Earth’s surface several addresses.
  • Fragmentation in transit. IPv4 routers fragment packets that are too big for the next link. This is expensive on modern routers with hardware-based forwarding. IPv6 only fragments at the source, using PMTUD.
  • Header complexity. IPv4 options are processed by every router along the path. IPv6 extension headers are processed only by the endpoints (except Hop-by-Hop).
  • Broadcast. ARP requests broadcast; IPv6 uses solicited-node multicast, so a host only processes the NS for the address it cares about.
  • NAT. IPv6’s address space is large enough that every device can have a globally routable address. NAT is not part of the design. (Operators still use NAT66 in narrow cases, but the protocol does not require it.)

How VyOS exposes IPv6 state

vyos@vyos:~$ show ipv6
  Interface        Address
  ---------        -------
  eth0             2001:db8::1/64
  eth0             fe80::5054:ff:fe12:3456/64
  lo               ::1/128
vyos@vyos:~$ show ipv6 neighbor
  IPv6 Address                    MAC Address        Interface
  -----------                    -------------      ---------
  fe80::1                        52:54:00:aa:bb:cc  eth0
  2001:db8::5                    52:54:00:11:22:33  eth0
  INCOMPLETE entries: 0

INCOMPLETE means a Neighbor Solicitation has been sent and no Neighbor Advertisement has come back. STALE means the entry is valid but unused for a while. REACHABLE means used within the last reachable-time window. DELAY and PROBE mean the kernel is verifying the entry is still valid.

How the result is validated

show ipv6
show ipv6 neighbor
ip -6 addr show
ip -6 neigh show
ip -6 route show
ping6 fe80::1%eth0
ping6 2001:db8::1
traceroute6 2001:db8::1
tcpdump -n -i eth0 ip6

The first two are the VyOS view; the next three are the Linux kernel view; the next two prove reachability; the last one proves the packets are on the wire. The VyOS view and the Linux view must agree. A neighbour entry that shows in one but not the other is a state divergence that needs investigation.

How it fails

The production failure modes the engineer must recognise:

  • ICMPv6 blocked on the firewall. NDP fails. The host has no default route and no working neighbour cache. All unicast IPv6 traffic fails.
  • Duplicate link-local from EUI-64. Two VyOS VMs with the same MAC (a hypervisor misconfiguration) generate the same link-local. NDP sees the second advertisement and flips the neighbour cache. Traffic alternates between the two hosts.
  • Link-local filtered as “private”. A firewall rule dropping fe80::/10 breaks router discovery. Hosts default to link-local-only addresses and cannot reach the global internet.
  • MTU 1280 missed. IPv6 requires the path to carry 1280 bytes minimum. A tunnel with lower MTU that does not run PMTUD correctly silently drops packets larger than its MTU. Lesson vyos-li-03-pmtud covers PMTUD in depth.
  • No IPv6 default route. RAs suppressed, RS unanswered, or default router flag (router-lifetime) cleared. Hosts have addresses but no route off-link.

Rollback

The recovery from a bad IPv6 fundamentals state:

  • ICMPv6 blocked: delete firewall name ... rule ... and the allow rule re-added before commit; save.
  • Duplicate link-local: regenerate the MAC at the hypervisor and reboot the VM.
  • Wrong link-local filter: remove the offending rule, commit; save.
  • Missing MTU: reconfigure the tunnel MTU to at least 1280 and verify PMTUD is functional.

Production discipline

Cross-course references

The Linux course’s XIX-Linux-NetFoundations covers the kernel IPv6 stack and sysctl knobs in detail. The Proxmox course’s XXIX-Proxmox-Networking covers the host-side IPv6 in the hypervisor. The OPNsense course’s I-OPNsense-NetFoundations covers the equivalent IPv6 concepts from the firewall perspective. The VyOS lesson vyos-i-06-arp-vs-ndp covers the ARP-vs-NDP comparison that this lesson builds on.

Quiz

Knowledge check · 4 questions

  1. Q1. Which protocol replaces ARP for IPv6?

  2. Q2. An IPv6 router that receives a transit packet too large for the next link drops it and returns ICMPv6 Packet Too Big rather than fragmenting it.

  3. Q3. A host has an IPv6 address but no default route and cannot reach the global internet. The RA flag on the upstream router is set to router-lifetime=0. What does that mean?

    Routers send Router Advertisement messages with a Router Lifetime field. Zero means the router is telling hosts to remove it from the default router list. Hosts that see this stop using the router as a default.

  4. Q4. An operator turns off ICMPv6 on the firewall for security. After the change, IPv6 traffic stops working but IPv4 traffic is fine. Why?

    ICMPv6 carries NDP, Router Advertisement, and PMTUD. Blocking all ICMPv6 breaks neighbour resolution, which breaks all unicast IPv6. IPv4 still works because its critical protocols (ARP, ICMPv4) are different.

Passing score: 75%. Answers are checked in this browser.