VyOSXXI · OSPFv3 / IPv6 RoutingIPv6 routing
OSPFv3 concept — IPv6 link-state, link-local source, per-link semantics
What you'll learn
- Explain why OSPFv3 is an IPv6-only protocol that does not carry IPv4 prefixes
- Recognise the link-local source-address rule and why OSPFv3 packets originate from fe80::/64
- Distinguish per-link OSPFv3 operation from OSPFv2's per-subnet network statement
- Read the new OSPFv3 LSA format and identify the removed prefix field and added U-bit / S-bit / R-bit
- Recognise the production failure modes that follow from the protocol redesign
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
OSPFv3 is not OSPFv2 with longer addresses. The protocol was deliberately rewritten for IPv6: the LSA format changed, the source address changed, the address-family relationship changed, and the network-statement model changed. An operator who treats OSPFv3 as “OSPF for IPv6” misses the architectural shift and ships fragile deployments.
This lesson covers the five conceptual changes that matter for the VyOS 1.5 LTS operator:
- IPv6-only protocol. OSPFv3 carries IPv6 prefixes. OSPFv2 carries IPv4 prefixes. They are separate processes with separate state, separate adjacencies, and separate LSDBs.
- Link-local source address. OSPFv3 packets always originate
from the interface’s
fe80::/64address. Global unicast addresses are not used as source. - Per-link operation. OSPFv3 runs on a link, not on a subnet. IPv6 subnets can have many prefixes on a single link; OSPFv3 does not need to know which prefix is on the link.
- LSA format redesign. OSPFv3 LSAs no longer carry the prefix in the body. The body carries a topology descriptor (the link it advertises) and the prefix lives in a separate LSA.
The protocol process boundary
On VyOS 1.5 LTS the OSPFv2 and OSPFv3 processes are separate
daemons (ospfd and ospf6d). They share the underlying FRR
infrastructure but they have:
- Separate configuration blocks:
set protocols ospf ...for OSPFv2,set protocols ospfv3 ...for OSPFv3. - Separate adjacencies on the wire: OSPFv2 Hellos go to
224.0.0.5, OSPFv3 Hellos go toff02::5. - Separate LSDBs: OSPFv2 Type 1 / Type 2 / Type 3 / Type 4 / Type 5 / Type 7 LSAs in IPv4 form; OSPFv3 has the same LSA types in IPv6 form plus new types (Type 8 Link-LSA, Type 9 Intra-Area-Prefix-LSA).
- Separate RIBs:
show ip route ospffor OSPFv2 routes,show ipv6 route ospf6for OSPFv3 routes.
The two processes do not exchange routes by themselves. To move a route from OSPFv2 to OSPFv3 (or vice versa) the operator configures a redistribution block under both processes.
flowchart LR
subgraph "OSPFv2 process (ospfd)"
A1["ipv4 LSDB"]
A2["ipv4 RIB"]
end
subgraph "OSPFv3 process (ospf6d)"
B1["ipv6 LSDB"]
B2["ipv6 RIB"]
end
subgraph "Linux kernel"
K1["ip route table<br/>main IPv4"]
K2["ip -6 route table<br/>main IPv6"]
end
A1 --> A2 --> K1
B1 --> B2 --> K2
A2 -. "redistribute<br/>(operator config)" .-> B2
B2 -. "redistribute<br/>(operator config)" .-> A2
The architectural separation is deliberate. RFC 5838 added an address-family mode to OSPFv2 (sometimes called “AF OSPFv2” or “OSPFv2 multi-address-family”) that allows one OSPFv2 process to carry IPv4 and IPv6 prefixes, but VyOS 1.5 LTS and FRR support the cleaner “OSPFv3 for IPv6 + OSPFv2 for IPv4” model. The operator who runs both is responsible for keeping them aligned through redistribution.
The link-local source-address rule
OSPFv3 packets always carry the sender’s link-local IPv6 address as the source. Global unicast addresses are never used as the source of OSPFv3 control packets. The consequence is that:
- The Hello packet’s source is
fe80::<interface-id>. - The neighbour’s neighbour-id is the link-local address, not a global address.
- A router-id still exists (a 32-bit opaque value), but it is not
sourced from IPv4 space; it is the OSPFv3 router-id, configured
explicitly under
set protocols ospfv3 parameters router-id.
sequenceDiagram
participant R1 as R1 (eth0 fe80::1)
participant R2 as R2 (eth0 fe80::2)
R1->>R2: Hello src=fe80::1 dst=ff02::5<br/>router-id=10.255.0.1
R2->>R1: Hello src=fe80::2 dst=ff02::5<br/>router-id=10.255.0.2
Note over R1,R2: Source = link-local<br/>router-id = opaque value
Note over R1,R2: Adjacency formed<br/>using link-local as next-hop
The operational consequence is that the OSPFv3 next-hop on a route is always the neighbour’s link-local address. When the operator debugs “the route is installed but traffic blackholes,” the answer is almost always that the kernel cannot resolve the link-local next-hop — typically because the route entry has been overwritten by a static route, or because an RA-advertised default has a higher administrative distance.
Per-link operation
OSPFv3 runs on the link, not on the subnet. An IPv6 link can have many prefixes (a global unicast, a unique-local, a link-local, potentially several more); OSPFv3 does not need to know which prefixes are on the link because the LSA no longer carries a prefix. The link is identified by the interface-id, which is local to the router.
The operational consequence is that the operator does not write
set protocols ospfv3 area 0 interface eth0 prefix 2001:db8::/64
on VyOS — there is no such syntax. Instead:
set protocols ospfv3 area 0 interface eth0
The interface is in area 0; the addresses on the interface are discovered by the protocol. The global unicast prefixes on the interface are advertised by the Link-LSA (Type 8) and the Intra-Area-Prefix-LSA (Type 9); the topology (which router is attached to which link) is advertised by the Router-LSA (Type 1).
flowchart TB
subgraph "IPv6 link 2001:db8:1::/64"
R1["R1<br/>fe80::1<br/>2001:db8:1::1"]
R2["R2<br/>fe80::2<br/>2001:db8:1::2"]
NET["2001:db8:1::/64 prefix"]
end
subgraph "OSPFv3 LSDB on R1"
L1["Type 1 Router-LSA<br/>R1 is connected to R2"]
L8["Type 8 Link-LSA<br/>2001:db8:1::/64 lives here"]
L9["Type 9 Intra-Area-Prefix-LSA<br/>references L1"]
end
R1 -- "Type 1: topology" --> L1
R1 -- "Type 8: prefix lives here" --> L8
R1 -- "Type 9: prefix -> LSA" --> L9
The OSPFv2 model is the opposite: the network statement carries
the prefix (10.0.0.0/24), and the protocol matches the prefix
against interface addresses to find the interfaces to enable.
The new LSA format
The most consequential change is that OSPFv3 Type 1 Router-LSAs no longer carry a prefix. The LSA body is:
| Field | Purpose |
|---|---|
| LSA header | Type 1, router-id, sequence, age, checksum |
| Options | U-bit (untreated), S-bit (Stub), R-bit (Router is reachable) |
| Type | Stub, transit, p2p, virtual-link |
| Link-ID | The neighbour router-id (transit) or interface-id (stub) |
| Interface ID | Local interface identifier |
| Neighbor Interface ID | Remote interface identifier |
| Metric | Cost |
Notice: no IPv4 address, no IPv6 address, no prefix. The LSA describes topology, not addressing. The prefix comes from the Intra-Area-Prefix-LSA (Type 9), which says “the prefix 2001:db8:1::/64 lives on the link advertised by Type 1 LSA X.”
The three bits in the Options field are new in OSPFv3:
- U-bit. “Untreated” — the LSA should be propagated outside the area without translation. Default set; cleared by stub-area redistribution.
- S-bit. “Stub” — this is a stub area; it does not carry external (Type 5) LSAs.
- R-bit. “Router” — this bit is set when the originating router is reachable for forwarding. Used by the ABR’s Type 3 summarisation logic; cleared when the originator is not participating in forwarding (a transit-only router).
The R-bit in particular changes the operational behaviour of multi-area designs. A Type 3 Summary-LSA carries the R-bit to indicate whether the prefix is reachable through a router that is itself participating in forwarding. A downstream router that receives a Type 3 with R-bit clear knows the originator is not forwarding traffic; SPF will still calculate the path but the forwarding may fail.
Comparing OSPFv2 and OSPFv3 at the protocol level
| Aspect | OSPFv2 | OSPFv3 |
|---|---|---|
| RFC | 2328 | 5340 |
| Address family | IPv4 only | IPv6 only |
| Source address | Interface primary IPv4 | Link-local fe80::/64 |
| Hello destination | 224.0.0.5 | ff02::5 |
| DR/BDR destination | 224.0.0.6 | ff02::6 |
| Network statement | network 10.0.0.0/24 area 0 | interface eth0 area 0 |
| Router-LSA carries prefix | Yes (Type 1) | No (Type 1 carries topology, Type 9 carries prefix) |
| Authentication | Built into the protocol (simple-text / MD5 / SHA) | IPsec AH / ESP, or OSPFv3 authentication trailer (RFC 7166) |
| Configuration block | set protocols ospf ... | set protocols ospfv3 ... |
| Operational commands | show ip ospf ... | show ipv6 ospf6 ... |
The authentication row is worth highlighting. OSPFv2 carries authentication in the OSPF header itself; OSPFv3 abandoned that mechanism (because the protocol no longer wants to be in the business of authentication) and relies on IPsec for the same property, with RFC 7166 adding an OSPFv3 authentication trailer that is functionally similar to OSPFv2’s trailer.
The router-id row is also worth highlighting. OSPFv3 has a 32-bit
router-id that is configured explicitly (typically using a
/32 from the operator’s loopback range, even though the loopback
itself is IPv4 — the router-id is opaque, not an IPv4 address).
If the router-id is not configured, FRR derives it from the
highest IPv4 address on the router, which can change after a
restart or after an interface is reconfigured. Production always
sets the router-id explicitly.
Production failure modes that follow from the redesign
The conceptual changes produce specific operational failures:
- No IPv4 prefixes in OSPFv3. The operator configures OSPFv3 expecting it to advertise the IPv4 prefixes on the router. It does not. To carry IPv4 in an OSPFv3 process, the operator uses RFC 5838 AF mode (FRR does not implement this by default in VyOS 1.5 LTS; the standard answer is to run OSPFv2 alongside OSPFv3).
- Link-local as source breaks access-list filtering. The
upstream firewall has a rule “permit OSPF from 10.0.0.0/24 to
224.0.0.5”. OSPFv3 is not from 10.0.0.0/24, it is from
fe80::/64. The rule needs to be re-written for OSPFv3. - Per-link operation hides prefixes. The operator looks at
show ipv6 ospf6 interfaceand expects to see the prefixes. They are not there; they live in the Type 9 LSAs. - Authentication gaps. OSPFv2 had MD5 and SHA authentication built in. OSPFv3 relies on IPsec, which means an ACL / encryption-domain configuration must accompany the OSPFv3 configuration. Forgetting the IPsec piece means OSPFv3 runs unauthenticated.
flowchart TB
subgraph "Conceptual confusion"
CC1["OSPFv3 advertises IPv4?"]
CC2["Why fe80:: in OSPF logs?"]
CC3["Prefix not on interface?"]
CC4["Auth needed but not configured?"]
end
subgraph "Operational fix"
F1["Run OSPFv2 alongside"]
F2["Update ACLs for fe80::/64"]
F3["Type 9 carries prefix"]
F4["Add IPsec / RFC 7166"]
end
CC1 --> F1
CC2 --> F2
CC3 --> F3
CC4 --> F4
Rollback
The OSPFv3 configuration rollback path:
# Capture the running configuration before the change
show configuration commands | save /tmp/ospfv3-concept-$(date +%s).txt
# Compare
compare
# Commit with a short confirm window
commit-confirm 5
# Rollback if needed
rollback 1
commit
The commit-confirm window is essential because OSPFv3 adjacency formation is dependent on link-local addresses and IPv6 reachability. If the change removes the IPv6 gateway that the operator is using to access the router, the operator is locked out without a console path.
Production discipline
Cross-course references
The VyOS lessons on IPv6 (vyos-xi-01-ipv6-fundamentals,
vyos-xi-06-ipv6-troubleshoot) cover the IPv6 primitives this
lesson assumes. The lessons on OSPF fundamentals
(vyos-xviii-01-link-state, vyos-xviii-03-lsa-types) cover the
shared concepts. The OSPF configuration lessons
(vyos-xix-01-ospf-basics through vyos-xix-06-ospf-cost-tuning)
cover the OSPFv2 idiom; the same mental model does not apply
to OSPFv3, which is the point of this lesson. The OSPF
troubleshooting part (vyos-xxii-01-neighbour-stuck through
vyos-xxii-06-missing-route) covers failure modes that apply
to both OSPFv2 and OSPFv3, with OSPFv3-specific examples in
the OSPFv3 troubleshooting lesson. The Linux course’s
V-Linux-NetConfig covers the kernel IPv6 routing-table
primitives that OSPFv3 installs into.
Quiz
Knowledge check · 4 questions
Q1. Which address does an OSPFv3 Hello packet use as its source on a VyOS router?
Q2. OSPFv3 Type 1 Router-LSAs carry the IPv6 prefixes advertised by the originating router.
Q3. An operator enables OSPFv3 on a VyOS router. The configuration is `set protocols ospfv3 area 0 interface eth0`. The operator expected to see the global unicast prefix 2001:db8:1::/64 advertised. It is not. What is the missing piece?
The operator configures OSPFv3 with `set protocols ospfv3 parameters router-id 10.255.0.1` and `set protocols ospfv3 area 0 interface eth0`. The interface has address 2001:db8:1::1/64. After commit, `show ipv6 ospf6 neighbor` shows the adjacency formed. `show ipv6 route ospf6` on a remote router shows no 2001:db8:1::/64 prefix. The operator expects to see the prefix but does not.
Q4. An operator enables OSPFv3 between two routers and configures IPsec to authenticate the OSPFv3 packets. The OSPFv3 adjacency does not form. The operator sees OSPFv3 Hellos in tcpdump on one side but not the other. What is the likely cause?
Two routers R1 and R2 have OSPFv3 enabled on eth0. The operator configures an IPsec encryption domain that should protect OSPFv3 traffic between fe80::1 and fe80::2. The adjacency stays in Init. tcpdump on R1 shows OSPFv3 Hellos going out, but no Hellos coming back. tcpdump on R2 shows no OSPFv3 Hellos at all.
Passing score: 75%. Answers are checked in this browser.