IPv6 troubleshooting — ping6, traceroute6, neighbour cache, MTU 1280, fragmentation
What you'll learn
- Run ping6 with the right interface and zone identifier for link-local targets
- Read the IPv6 neighbour cache and interpret INCOMPLETE / STALE / REACHABLE
- Recognise the 1280-byte MTU floor and the no-fragmentation-in-transit rule
- Diagnose Path MTU Discovery failures and apply the production fixes
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
IPv6 troubleshooting — ping6, traceroute6, neighbour cache, MTU 1280, fragmentation
IPv6 connectivity incidents look identical to IPv4 incidents at first glance — “the host cannot reach the server” — and then the operator discovers that IPv6 adds a layer of behaviour that IPv4 does not have. Link-local addresses need a zone identifier. The neighbour cache has states IPv4 does not have. The MTU floor is 1280, not 576. Routers do not fragment in transit, so PMTUD failures look like silent packet loss rather than “fragmentation needed” DF-set behaviour.
This lesson walks the operator through the diagnostic commands,
the state interpretation, and the failure modes that surface
when the data plane and the control plane disagree. It builds
on the foundational IPv6 lessons in Part XI and ties back to
the troubleshooting methodology from
vyos-lii-02-evidence-first.
ping6 — with the right zone identifier
sequenceDiagram
autonumber
participant H as Host<br/>2001:db8:1::1
participant R as Router<br/>2001:db8:1::2
H->>R: ICMPv6 Echo Request (type 128)<br/>src 2001:db8:1::1 dst 2001:db8:1::2
R-->>H: ICMPv6 Echo Reply (type 129)
The basic ping6:
vyos@vyos:~$ ping6 2001:db8:1::2
PING 2001:db8:1::2(2001:db8:1::2) 56 data bytes
64 bytes from 2001:db8:1::2: icmp_seq=1 ttl=64 time=0.4 ms
64 bytes from 2001:db8:1::2: icmp_seq=2 ttl=64 time=0.3 ms
To ping a link-local address, the operator must add a zone identifier (the interface name) so the kernel knows which interface to source from and which neighbour to look up:
vyos@vyos:~$ ping6 fe80::1%eth0
PING fe80::1%eth0(fe80::1%eth0) 56 data bytes
64 bytes from fe80::1%eth0: icmp_seq=1 ttl=64 time=0.4 ms
Without the zone identifier, the kernel does not know which
link the link-local address belongs to. Every interface has a
fe80::/64 link-local; the operator must say which one.
Useful ping6 options:
-c <count>— number of echoes.-I <interface>— source interface (also acts as zone identifier for link-local).-s <size>— payload size. The default 56 bytes gives a 64- byte ICMPv6 payload; use-s 1300to test near the MTU.-W <seconds>— per-echo timeout.-M do— set the Don’t Fragment bit (always set in IPv6) and report if the path needs fragmentation.
vyos@vyos:~$ ping6 -c 3 -s 1300 -M do 2001:db8:ffff::1
PING 2001:db8:ffff::1(2001:db8:ffff::1) 1300 data bytes
ping: local error: Message too long, mtu=1280
The “Message too long, mtu=1280” output is ping6 reporting a PMTUD failure. The packet was too big for a 1280-MTU link on the path and the kernel learned the lower MTU via an ICMPv6 Packet Too Big.
traceroute6 — finding the failing hop
sequenceDiagram
autonumber
participant H as Host
participant R1 as Router 1
participant R2 as Router 2
participant R3 as Router 3
participant T as Target
H->>R1: hop-limit=1
R1-->>H: ICMPv6 Time Exceeded
H->>R2: hop-limit=2
R2-->>H: ICMPv6 Time Exceeded
H->>R3: hop-limit=3
R3-->>H: ICMPv6 Time Exceeded
H->>T: hop-limit=N
T-->>H: ICMPv6 Echo Reply
traceroute6 works the same as traceroute for IPv4 but uses ICMPv6 Echo Request with increasing hop-limit values. Each router along the path decrements the hop-limit and, if it reaches zero, sends back an ICMPv6 Time Exceeded (type 3).
vyos@vyos:~$ traceroute6 2001:db8:ffff::1
traceroute to 2001:db8:ffff::1 (2001:db8:ffff::1), 30 hops max, 80 byte packets
1 2001:db8:1::2 (2001:db8:1::2) 0.412 ms 0.387 ms 0.371 ms
2 2001:db8:2::1 (2001:db8:2::1) 4.213 ms 4.198 ms 4.182 ms
3 2001:db8:ffff::1 (2001:db8:ffff::1) 8.401 ms 8.388 ms 8.372 ms
The operator reads the output top-down. The first hop where
the output goes from an IP with milliseconds to * * * is the
failing hop. Common failure shapes:
* * *all the way — the destination is unreachable or ICMPv6 is blocked.- A hop where the IP goes to ” * ” then resumes — the hop de-prioritised ICMPv6 responses, but traffic still flows.
- The last hop returns
!N(Network unreachable) or!H(Host unreachable) — the target’s neighbour is missing.
Useful traceroute6 options:
-s <src>— source address (must be on the router).-i <interface>— source interface.-m <max-hops>— maximum hops.-q <nqueries>— queries per hop.
The IPv6 neighbour cache
stateDiagram-v2
[*] --> INCOMPLETE: NS sent, no NA yet
INCOMPLETE --> REACHABLE: NA received within reachable-time
INCOMPLETE --> [*]: NS retries exhausted
REACHABLE --> STALE: reachable-time elapsed without use
STALE --> DELAY: first packet sent to entry
DELAY --> PROBE: delay-time elapsed
PROBE --> REACHABLE: NA received
PROBE --> [*]: probe retries exhausted
The neighbour cache is the kernel’s record of IPv6 address →
MAC mappings. ip -6 neigh show lists it.
vyos@vyos:~$ ip -6 neigh show
fe80::1 dev eth0 lladdr 52:54:00:aa:bb:cc REACHABLE
2001:db8:1::5 dev eth0 lladdr 52:54:00:11:22:33 STALE
2001:db8:1::10 dev eth0 INCOMPLETE
State meanings:
- INCOMPLETE — an NS has been sent but no NA has come back. The kernel is resolving. If this persists, NDP is broken.
- REACHABLE — the entry was recently confirmed (NA received in the last reachable-time window, default 30 seconds).
- STALE — the entry is in the cache but has not been confirmed within the reachable-time window. The first packet sent to it triggers DELAY / PROBE.
- DELAY — a packet was sent; the kernel is waiting briefly to see if upper-layer confirmation arrives (e.g. TCP ACK).
- PROBE — the kernel is sending unicast NS to verify the entry is still valid.
- FAILED — the entry could not be resolved. The neighbour is unreachable.
An entry stuck in INCOMPLETE for the default gateway is a classic “IPv6 broke after a firewall change” symptom. The firewall is blocking the NA back.
The MTU 1280 floor
flowchart TB
L1["Ethernet link<br/>MTU 1500"] --> T[Tunnel<br/>MTU 1380]
T --> L2["Ethernet link<br/>MTU 1500"]
L2 --> T2[Tunnel<br/>MTU 1280]
T2 --> L3["Server<br/>MTU 1500"]
Note["Path MTU is 1280<br/>all hosts must fragment<br/>to fit"]
RFC 8200 mandates that every IPv6 link support an MTU of at least 1280 bytes. The path MTU is the minimum MTU along the path from source to destination. If any link is smaller than the packet, the packet cannot be sent as-is.
Common MTU ceilings in production:
- Ethernet: 1500 (typical)
- Ethernet with VLAN tag: 1496 (typical)
- GRE tunnel: 1476 (Ethernet MTU minus 24 bytes GRE overhead)
- IPsec tunnel mode: 1380 (Ethernet MTU minus 120 bytes ESP / IPsec overhead)
- WireGuard: 1428 (Ethernet MTU minus 80 bytes overhead)
- VXLAN: 1450 (Ethernet MTU minus 50 bytes overhead)
A misconfigured tunnel with an effective MTU below 1280 is broken and IPv6 packets that try to cross it fail.
Fragmentation — the source, not the network
sequenceDiagram
autonumber
participant S as Source
participant R1 as Router 1
participant R2 as Router 2 (low MTU link)
participant T as Target
S->>R1: packet size 1500
R1->>R2: packet size 1500
R2-->>S: ICMPv6 Packet Too Big<br/>MTU 1280
S->>R1: 2x fragments size 1280 with Fragment header
R1->>R2: 2x fragments size 1280
R2->>T: 2x fragments size 1280
T-->>S: ICMPv6 Echo Reply (reassembled)
In IPv4, routers fragment packets that are too big for the next link. In IPv6, routers do not fragment in transit. The router sends an ICMPv6 Packet Too Big (type 2) back to the source with the MTU of the constrained link. The source then fragments the packet using a Fragment extension header.
This is the PMTUD mechanism. The source host maintains a path MTU cache, learns the minimum MTU from Packet Too Big messages, and uses the smallest MTU seen for that destination.
PMTUD has two known failure modes:
- The ICMPv6 Packet Too Big is filtered. A firewall drops ICMPv6 type 2 messages. The source never learns the lower MTU and keeps sending packets that are too big. They are silently dropped at the constrained router.
- The source is not PMTUD-capable. Old hosts (Windows XP and earlier, very old embedded devices) do not implement PMTUD for IPv6. They send a fixed-size packet and silently fail.
The VyOS lessons vyos-li-03-pmtud and
vyos-li-04-mss-clamping cover PMTUD in detail.
Capturing IPv6 packets with tcpdump
vyos@vyos:~$ tcpdump -i eth0 -n ip6
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:00:01.123 IP6 2001:db8:1::1 > 2001:db8:1::2: ICMPv6, echo request, seq 1
12:00:01.124 IP6 2001:db8:1::2 > 2001:db8:1::1: ICMPv6, echo reply, seq 1
12:00:08.001 IP6 fe80::1 > ff02::2: ICMPv6, router solicitation
12:00:09.123 IP6 fe80::2 > fe80::1: ICMPv6, router advertisement
Useful tcpdump flags for IPv6:
-n— no name resolution.ip6— capture only IPv6 packets.icmp6— capture only ICMPv6 packets.port 547— capture DHCPv6 traffic.-e— show link-layer headers (useful for NDP messages that carry MAC in the option).
For deeper NDP inspection:
vyos@vyos:~$ tcpdump -i eth0 -n -e icmp6
12:00:08.001 IP6 fe80::1 > ff02::2: ICMPv6, router solicitation
12:00:09.123 IP6 fe80::2 > fe80::1: ICMPv6, router advertisement, lifetime 1800, reachable time 0, retrans timer 0, prefix 2001:db8:1::/64, mtu 1500
The -e flag shows the Ethernet header so the operator can
confirm the source MAC and the multicast destination MAC.
How the result is validated
ping6 -c 3 2001:db8:1::1
ping6 fe80::1%eth0
traceroute6 2001:db8:ffff::1
tracepath6 2001:db8:ffff::1
show ipv6
show ipv6 neighbor
ip -6 neigh show
ip -6 route show
ip -6 addr show
tcpdump -i eth0 -n ip6
The first two are basic reachability. The next two are path
discovery (tracepath6 does PMTUD by default). The next three
are the VyOS and Linux state views. The last three are the
on-wire evidence.
A working state has REACHABLE or STALE entries in the
neighbour cache, reachable IPs in show ipv6, ICMPv6 Echo
Replies in ping6, and ICMPv6 traffic visible in tcpdump.
How it fails
The production failure modes the engineer must recognise:
- NDP blocked. The neighbour cache shows entries stuck in INCOMPLETE. The firewall is dropping NS / NA.
- ICMPv6 Packet Too Big blocked. Large packets fail to a
destination. The neighbour cache is healthy.
tracepath6shows the path works at default MTU but large packets fail. - Link-local zone identifier wrong.
ping6 fe80::1without%eth0returnsconnect: Invalid argument. The kernel cannot decide which interface to use. - MTU 1280 not enforced. A tunnel with effective MTU below 1280 fails IPv6 completely. The link is misconfigured; fix the tunnel, not the host.
- Path MTU cached from a stale failure. A host learned a
low MTU from a transient Packet Too Big and has not retried.
Long-running connections stay below their optimal MTU.
Operators clear the path MTU cache with
ip -6 route flush cache(or the equivalent on the host OS). - Duplicate Address Detection loops. A host with a duplicate IPv6 address keeps sending NS to its own address. The neighbour cache on the router shows DAD in progress.
Rollback
The recovery from a bad IPv6 state:
- NDP blocked:
delete firewall name ... rule ...that denied ICMPv6 and re-add the allow rule beforecommit; save. - PMTUD blocked: allow ICMPv6 type 2 (Packet Too Big) at the firewall.
- Wrong zone identifier: re-run
ping6with the correct%ethNsuffix. - Stale PMTU cache:
ip -6 route flush cacheor restart the long-running connection. - Duplicate address: reconfigure the host with a unique IPv6 address; check the upstream RA does not collide.
Production discipline
Cross-course references
The Linux course’s XIX-Linux-NetFoundations covers the
kernel IPv6 diagnostic primitives (/proc/net/if_inet6,
/proc/sys/net/ipv6/, neighbour cache internals). The VyOS
lessons vyos-xi-01-ipv6-fundamentals,
vyos-xi-02-ipv6-addressing,
vyos-xi-03-ipv6-router-advertisements,
vyos-xi-04-dhcpv6, and vyos-xi-05-ipv6-routing cover the
protocol and configuration layers this lesson builds on. The
lessons vyos-li-03-pmtud and
vyos-li-04-mss-clamping cover PMTUD in depth. The lesson
vyos-lii-02-evidence-first covers the troubleshooting
methodology.
Quiz
Knowledge check · 4 questions
Q1. Which ping6 syntax reaches a link-local IPv6 address?
Q2. An IPv6 router drops a packet that is too big for the next link and returns ICMPv6 Packet Too Big to the source.
Q3. An operator can ping6 the upstream router but cannot reach a server beyond it. The neighbour cache for the upstream is REACHABLE. ping6 with `-s 1300 -M do` fails. What is happening?
Default ping6 sends a 64-byte packet which fits any IPv6 path. The -s 1300 -M do probe sends a 1300-byte packet with the Don't Fragment bit set (always on in IPv6). If the path MTU is below 1300, the router sends Packet Too Big and the ping fails. The neighbour cache being healthy means NDP is working; the failure is at a hop on the path with a lower MTU.
Q4. An operator configures an IPv6 firewall rule that allows ICMPv6 Echo but blocks all other ICMPv6. Hosts can ping the router but cannot reach the internet. Why?
ICMPv6 is not optional in IPv6. Blocking types other than Echo Request / Echo Reply (128 / 129) breaks NDP (types 135 / 136), router discovery (types 133 / 134), and PMTUD (type 2). With only Echo allowed, hosts can ping but cannot resolve next-hops and cannot learn MTU constraints.
Passing score: 75%. Answers are checked in this browser.