Add OSPFv3 support for FortiOS#3451
Merged
Merged
Conversation
The netlab FortiOS OSPF template supported only OSPFv2, but the device manifest
declared neither ospf.ipv4 nor ospf.ipv6, so _routing.py auto-enabled ospf.af.ipv6
on any node that had IPv6 OSPF interfaces. The single, address-family-agnostic
ospf/fortios.j2 then ran its IPv4-only body against those interfaces and failed
in ansible.utils.ipaddr ('width' is undefined) the moment it formatted
intf.ipv4 on an IPv6-only link. This left IPv6 iBGP labs, which need an IPv6 IGP
to carry loopback reachability, with no usable FortiOS IGP.
Render both OSPF instances from a single ospf_config(proto, intf_list, ospf)
macro, invoked once per active address family. The caller pre-filters the
interface list by address family and passes the macro only the interfaces that
belong in that instance, so address-family correctness is established once at
the boundary rather than re-checked throughout the body. proto ('ospf' or
'ospf6') is both the FortiOS configuration keyword and the discriminator for the
few places the two instances diverge.
Three constraints are not apparent from the diff:
- The OSPFv2 interface list must contain only interfaces that have an IPv4
address. FortiOS binds an interface to its area through a prefix in
`config network`, which requires the interface's IPv4 subnet; OSPFv3 instead
binds the area with `set area-id` inside `config ospf6-interface`.
- `config area` is emitted before the interface stanza, because FortiOS rejects
`set area-id` for an area that has not yet been defined ("Please input a
defined area id!").
- OSPFv3 authentication on FortiOS is IPsec-based; plaintext and MD5 keys do not
apply, so the password line is emitted for OSPFv2 only.
No device-manifest change is required: AF support defaults to enabled unless
the device manifest disables it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ipspace
approved these changes
Jun 6, 2026
Owner
ipspace
left a comment
There was a problem hiding this comment.
Picture perfect. I love the description with detailed explanations and test results.
Thanks a million!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Apart from OSPFv3 support this PR also fixes a bug related to the fact that
the netlab FortiOS template shipped with OSPFv2 only, but this was not recorded.
The device manifest declares neither
ospf.ipv4norospf.ipv6, so_routing.pyauto-enables
ospf.af.ipv6on any node that has IPv6 OSPF interfaces. Thesingle, address-family-agnostic
ospf/fortios.j2then ran its IPv4-only bodyagainst those interfaces and failed in
ansible.utils.ipaddr('width' is undefined)the moment it tried to format
intf.ipv4on an IPv6-only link.This surfaced while bringing up IPv6 iBGP labs, which require an IPv6 IGP to
carry loopback reachability — FortiOS had none.
What
ospf/fortios.j2now renders both OSPF instances from a singleospf_config(proto, intf_list, ospf)macro, invoked once per active addressfamily inside the VDOM wrapper:
family, and calls the macro with
proto='ospf'for the IPv4 set andproto='ospf6'for the IPv6 set.protois both the FortiOS configuration keyword (config router ospf/config router ospf6,config ospf-interface/config ospf6-interface)and the discriminator for the few places the two instances diverge.
macro runs, address-family correctness is established once at the boundary:
the macro never sees an interface that does not belong in the instance it is
rendering, which is what makes the original
ipaddrfailure impossible.No device-manifest change is required: support is the default, and the
dispatcher's
ospf.af.*gates decide which instance renders.Device-specific constraints (notes for reviewers)
through a prefix in
config network, which needs the interface's IPv4 subnet.The IPv4 interface list must therefore exclude interfaces without an IPv4
address; this is enforced by the pre-filtering. OSPFv3 instead binds the area
with
set area-idinsideconfig ospf6-interface.set area-idunderconfig ospf6-interfacefails on the device with "Please input a definedarea id!" unless the area already exists, so
config areais emitted beforethe interface stanza.
ospf.areasalready aggregates every area theinterfaces use, so the ordering alone is sufficient.
set passive-interfacelist, not aper-interface flag.
apply, so the password line is emitted for OSPFv2 only.
Testing
Verified live against a FortiOS 8.0.0 DUT (libvirt; FRR probes on clab), one
lab at a time, using the OSPFv2 and OSPFv3 integration suites under
tests/integration/ospf/. After excluding topologies that depend on FortiOSfeature gaps unrelated to this change (the
bgp/bfd/vrfmodules, VLANinterfaces, unnumbered and link-local-only IPv6 interfaces, static-route
import), the eligible set is seven OSPFv2 and seven OSPFv3 topologies; all pass.
Two clarifications on the run:
30-timers,31-priority, and32-password, netlab deliberately skipsthe VRF-specific subtests on FortiOS (VRF OSPF is out of scope) and reports a
warning; the OSPF subtests themselves pass.
06-lb-prefixchecks an OSPFv3 LSA and can report the prefix as absent if itis validated before the LSA has propagated on a cold boot; a re-run after a
short wait confirms the loopback is advertised as
/128.Offline render checks (
netlab create) confirm per-address-family membership ona node with three links — dual-stack, IPv4-only, and IPv6-only: the IPv4-only
interface appears under
config router ospfonly, the IPv6-only interface underconfig router ospf6only, and the dual-stack interface under both.Docs
The per-platform OSPF support matrix and the IPv6 address-family table are
updated to mark FortiOS OSPFv3 as supported (
docs/module/ospf.md,docs/platforms.md).Out of scope
VRF OSPFv3, BFD for OSPFv3, redistribution/import, and default-route
origination are intentionally left out of this basic implementation.