OSPF on Linux Part 5: Troubleshooting OSPF on Linux
OSPF Deep Dive Part 10 laid out a vendor-neutral troubleshooting sequence: confirm Layer 1/2 and IP reachability first, then neighbor state, then LSDB content, then route installation, in that order, because each layer’s problems look different and chasing the wrong one wastes time. Part 11 turned that sequence into a three-vendor show-command table. This post adds FRR as a fourth column, then covers the failure modes that are specific to Linux and don’t have an equivalent on Cisco, FortiOS, or Junos at all.
The show-command table, now with FRR
| Task | Cisco IOS-XE | FortiOS | Junos | FRR (vtysh) |
|---|---|---|---|---|
| Neighbor states | show ip ospf neighbor | get router info ospf neighbor | show ospf neighbor | show ip ospf neighbor |
| Interface OSPF config/state | show ip ospf interface brief | get router info ospf interface | show ospf interface | show ip ospf interface brief |
| Full LSDB summary | show ip ospf database | get router info ospf database | show ospf database | show ip ospf database |
| One LSA in full detail | show ip ospf database router <id> | get router info ospf database router <id> | show ospf database extensive | show ip ospf database router <id> |
| Routes as OSPF calculated them | show ip route ospf | get router info routing-table ospf | show ospf route | show ip route ospf |
| Process-wide summary | show ip ospf | get router info ospf status | show ospf overview | show ip ospf |
| Live event debugging | debug ip ospf adj / debug ip ospf events | diagnose ip router ospf level info | show ospf log / traceoptions | debug ospf adj / debug ospf events |
The pattern from Part 11 holds: read the state field carefully. FRR appends the DR/BDR role directly to the state field the same way Cisco and FortiOS do, Full/DR, Full/- on a point-to-point link, the format LAB-LNX showed against CORE-CSR in Part 4. debug ospf ... commands are enabled per-session and don’t persist across a restart unless written into the config explicitly, same caveat as debug ip ospf on Cisco.
Failure modes that are specific to Linux
None of these have a real equivalent on an appliance, because an appliance’s vendor has already made the decision each one represents. On Linux, they’re all still open questions the operating system leaves to you.
IP forwarding is off by default. net.ipv4.ip_forward is 0 on a stock Linux install, and OSPF adjacencies form and the LSDB syncs perfectly normally with it off, because none of that requires forwarding, only that zebra can install routes and the interfaces can send and receive OSPF packets. What breaks silently is everything downstream: the router looks fully converged, show ip ospf neighbor says Full, show ip route ospf lists the expected routes, and transit traffic still doesn’t pass, because the kernel was never told to forward it in the first place. sysctl net.ipv4.ip_forward=1, and net.ipv4.conf.all.forwarding=1 if the interfaces were brought up before the change, persisted in /etc/sysctl.d/. Check this before anything protocol-specific, it’s a one-line fix for a symptom that otherwise looks like a routing problem.
A firewall dropping protocol 89. OSPF isn’t TCP or UDP, it runs directly over IP protocol 89, and a default-deny nftables or iptables ruleset written with only TCP and UDP in mind passes right over it, no rule matches, nothing logs, the packets are just gone. The fix is a rule that matches on protocol rather than port:
nft add rule inet filter input ip protocol ospf accept
or, iptables equivalent:
iptables -A INPUT -p ospf -j ACCEPT
This is worth checking specifically before assuming a hello-parameter mismatch from OSPF Deep Dive Part 1, because the symptom looks identical from the neighbor state table, stuck at Down, no neighbor entry at all, which is exactly the “nothing OSPF-specific has happened yet” row from Part 10’s troubleshooting table.
Multicast group membership. OSPF hellos on a broadcast segment go to 224.0.0.5 (AllSPFRouters), DR/BDR-directed updates go to 224.0.0.6 (AllDRouters). ospfd joins these groups on its own when an interface is enabled for OSPF, but a restrictive nftables multicast rule, an interface that came up before ospfd did, or a virtual interface (a veth pair, a bridge) that doesn’t propagate multicast the way a physical NIC does, can all block hello delivery specifically while leaving unicast traffic on the same link completely fine. ip maddr show <interface> lists the multicast groups an interface has actually joined, and confirming 224.0.0.5 is there is the fast check before looking anywhere else.
The wrong network namespace. A Linux box running FRR inside a container or a ip netns sandbox, the same primitive covered in Linux Networking from the Ground Up, has its own isolated network stack, and ospfd only sees the interfaces that exist inside its own namespace. An interface moved to a namespace after FRR started, or a veth end left in the wrong namespace during setup, produces no error from ospfd at all, the interface simply isn’t there from the daemon’s point of view. ip netns exec <ns> vtysh runs the CLI inside the correct namespace directly; ip netns exec <ns> ip link confirms which interfaces actually live there before spending time in ospfd’s own output.
veth MTU defaults. OSPF Deep Dive Part 7 covered ip ospf mtu-ignore as a diagnostic tool, not a fix, for an ExStart-stuck adjacency caused by mismatched MTU. Linux veth pairs default to 1500 like a physical Ethernet interface, so this usually isn’t a problem connecting to a physical router, but it becomes one the moment a veth pair sits behind a tunnel, an overlay, or a bridge with a lower MTU somewhere in the path, and the two ends of the OSPF adjacency disagree on what the link actually supports. ip link show <interface> reports the current MTU directly; matching it explicitly on both ends of a link is the actual fix, the same conclusion Part 7 reached for the appliance case.
tcpdump: the view none of the three appliances give you as easily
This is the genuine advantage of troubleshooting OSPF from a Linux box specifically: full packet capture is a command away, not a licensed feature or a separate diagnostic mode.
tcpdump -i eth0 -n proto ospf
proto ospf is a BPF filter Linux resolves to protocol 89 directly, no manual ip proto 89 needed, matching the net 10.0.0.0/24-style filters already used on the tcpdump deep dive post on this site. Capturing a hello exchange during ExStart shows the actual DBD sequence-number negotiation from OSPF Deep Dive Part 1’s state table happening on the wire, not just the state name ospfd reports after the fact, which is the fastest way to confirm a stuck ExStart really is an MTU disagreement, the DBD packet size in the capture will show it directly, rather than treating mtu-ignore as a first move instead of a last one.
That closes this series. Five posts: where FRR came from, why it’s the default choice today, how to install and configure it, a fourth router wired live into the OSPF Deep Dive lab, and where to look when any of it breaks, on the one platform in this whole run of posts where you get to watch the protocol happen instead of just being told the result.