VyOSII · Routing FundamentalsRouting primitives
Administrative distance — how a router prefers one source over another
What you'll learn
- Locate administrative distance in the right place — zebra's RIB, not the kernel FIB
- State the FRR 10 default distance for every routing source VyOS 1.5 can produce
- Explain the difference between distance and metric, and when each one is consulted
- Configure a non-default distance for static routes, OSPF and BGP in VyOS 1.5 syntax
- Diagnose a route-selection incident caused by a wrong distance
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-19
Administrative distance is the trust value FRR assigns to a route based on which routing source produced it. When two sources offer a route to the same prefix, FRR installs the one with the lower distance and leaves the other in the RIB, unselected.
Longest-prefix match runs first and is a different question: it picks which prefix answers a destination. Distance only ever compares candidate routes that cover the identical prefix. A /24 static and a /16 OSPF route never compete on distance at all — the /24 is more specific, so it wins on match length before distance is consulted.
The operator who understands distance can predict which route will be installed in any collision. The operator who does not spends hours on “the route I configured is not being used” incidents that come down to one number.
Where administrative distance actually lives
The Linux kernel has no concept of administrative distance. Its
routing table has a destination, a next-hop, a scope, a proto byte
recording who installed the entry, and a metric (properly, a
priority) used to order otherwise-identical entries. There is no field
for trust, and no arbitration between routing daemons.
That arbitration is zebra’s job. Every FRR daemon — bgpd, ospfd,
staticd, and the rest — offers its routes to zebra. Zebra keeps them
all in the RIB, picks a winner per prefix, and pushes only the winner
into the kernel FIB over netlink.
flowchart TB
S1["staticd<br/>0.0.0.0/0 distance 1"] --> RIB
S2["ospfd<br/>0.0.0.0/0 distance 110"] --> RIB
S3["bgpd<br/>0.0.0.0/0 distance 20"] --> RIB
RIB["zebra RIB<br/>all candidates for a prefix"] --> SEL{"lowest distance<br/>for this prefix"}
SEL --> FIB["kernel FIB<br/>one selected route"]
SEL -.->|"kept, not selected"| RIB
FIB --> FWD["forwarding"]
This is why the two views disagree, and why that disagreement is not a bug:
show ip route 0.0.0.0/0shows every candidate with its distance and marks the selected one. This is the view that explains a decision.ip route show 0.0.0.0/0shows only what zebra installed. This is the view that tells you what the box is forwarding on right now.
The distance table FRR 10 ships
These are zebra’s compiled-in defaults for the sources a VyOS 1.5 router can actually produce:
| Source | Distance | What produces it on VyOS |
|---|---|---|
| Connected | 0 | An address on an interface that is up |
| Local | 0 | The host route for the router’s own address |
| Kernel | 0 | A route the kernel installed and zebra learned over netlink — an IPv6 default from a Router Advertisement, for instance |
| Static | 1 | set protocols static route ..., including blackhole and reject routes |
| eBGP | 20 | set protocols bgp neighbor ... where the peer’s remote-as differs from system-as |
| OSPFv2 / OSPFv3 | 110 | set protocols ospf ... / set protocols ospfv3 ... |
| IS-IS | 115 | set protocols isis ... |
| RIP / RIPng | 120 | set protocols rip ... / set protocols ripng ... |
| iBGP | 200 | set protocols bgp neighbor ... where the peer’s remote-as equals system-as |
Two entries commonly quoted from vendor documentation are worth naming precisely so you do not go looking for them:
- eBGP and iBGP are one protocol with two distances. Zebra stores
a single BGP entry;
bgpdtells it 20 or 200 depending on whether the route was learned from an external or an internal peer. There is no separate “eBGP protocol” inshow ip route. - EIGRP is a Cisco protocol. FRR carries an
eigrpd, but VyOS 1.5 does not expose it in the configuration tree, so the classic 90/170 pair never appears on a VyOS box. If a design document quotes those numbers, it is describing a Cisco device in the same network, not this one.
FRR also carries defaults for sources this table omits — Babel, NHRP,
LDP, and several daemons VyOS does not surface. Read the number off
the box rather than out of memory: show ip route <prefix> prints the
distance it actually used, and that number is the one that decided the
outcome.
Distance versus metric
They are different comparisons run at different stages, and confusing them is the single most common source of “the numbers say I should win” tickets.
- Distance ranks sources. Lower is more trusted. Zebra compares distance across every candidate for a prefix, whatever protocol produced it.
- Metric ranks paths inside one source. Lower is better. OSPF cost, IS-IS metric and RIP hop count are metrics. A protocol has already used its own metric to choose which route it offers to zebra before zebra ever sees it.
Zebra compares metric only between two candidates that tie on distance. Since a tie on distance almost always means “two routes from the same protocol”, the metric comparison is nearly always within-protocol — which is exactly what it was designed for.
The practical consequence: an OSPF cost of 10 does not beat a static route, no matter how low you push it. Distance decides first, the static’s 1 beats OSPF’s 110, and the cost is never read.
Configuring a non-default distance
Static routes
set protocols static route 10.0.0.0/24 next-hop 192.0.2.1 distance 50
set protocols static route 0.0.0.0/0 next-hop 198.51.100.1 distance 200
set protocols static route 198.18.0.0/15 blackhole distance 254
The valid range is 1 to 255. There is no distance 0 for a static route, which is why a static can never displace a connected route.
The second line is the floating-static idiom: a distance of 200 is worse than OSPF’s 110 and worse than eBGP’s 20, so the route sits in the RIB unselected while any dynamic default exists, and becomes the selected default the moment the dynamic one is withdrawn.
OSPF
set protocols ospf distance global 110
set protocols ospf distance ospf intra-area 110
set protocols ospf distance ospf inter-area 110
set protocols ospf distance ospf external 110
distance global sets one value for every OSPF route. The
distance ospf sub-tree sets them per route class, and takes
precedence over distance global for the classes it names. Raising
external alone is the one variant with a routine use: it makes
routes OSPF learned by redistribution lose to something else without
touching OSPF’s view of its own area topology.
BGP
In VyOS 1.5, BGP distance is an address-family property, not a top-level one:
set protocols bgp system-as 65000
set protocols bgp address-family ipv4-unicast distance global external 20
set protocols bgp address-family ipv4-unicast distance global internal 200
set protocols bgp address-family ipv4-unicast distance global local 200
set protocols bgp address-family ipv4-unicast distance prefix 10.50.0.0/16 distance 250
external, internal and local correspond to routes from eBGP
peers, routes from iBGP peers, and locally-originated routes. The
distance prefix form overrides all three for one prefix, which is the
surgical option when a single prefix is arriving from the wrong place.
The DHCP-learned default route
A WAN interface running DHCP installs a default route whose distance VyOS lets you set directly:
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth0 dhcp-options default-route-distance 210
set interfaces ethernet eth0 dhcp-options no-default-route
The default value is 210 — deliberately worse than every IGP and every
ordinary static, so that a default learned from an ISP’s DHCP server
never silently outranks a default the operator or the IGP chose.
no-default-route suppresses the learned default entirely, which is
what you want on an interface that is DHCP-addressed for management
but must not become a path out.
Check the value on your own image with tab completion before designing around it; the point to internalise is the direction, which is that this route is meant to lose.
Reading the decision
The operational-mode commands that matter:
show ip route
show ip route 0.0.0.0/0
show ip route static
show ip route ospf
show ip route bgp
show ip route summary
show ip route <prefix> is the one that answers “why”. It prints one
“Routing entry” block per candidate, each with the distance FRR used,
and marks the selected one.
vyos@vyos:~$ show ip route 0.0.0.0/0Routing entry for 0.0.0.0/0
Known via "static", distance 1, metric 0, best
* 192.0.2.1, via eth0, weight 1
Routing entry for 0.0.0.0/0
Known via "ospf", distance 110, metric 10
10.0.0.2, via eth1, weight 1Illustrative output
Read it as three facts. The Known via string is the source. The
distance is the number that was compared. The best marker and the
* on the next-hop say which candidate zebra selected and installed;
the block without them is a route the router is holding in reserve,
not a route it is using.
The kernel side confirms the outcome and nothing more:
ip route show 0.0.0.0/0
ip route get 10.0.5.50
ip route get is worth the habit: it asks the kernel to run a real
lookup for one destination and report the entry it would use,
including the source address it would pick. That last part catches a
class of multi-WAN problem that a table dump does not.
Failure modes
The floating static is winning while the primary is healthy
The backup path is carrying production traffic. show ip route shows
the static marked best and the dynamic route present but unselected.
The distance direction has been inverted: the static was given a number lower than the dynamic route’s, so it is more trusted, so it wins. A floating route must be given a distance worse than everything it is backing up.
Fix: raise the static’s distance above the primary’s — 200 or higher
against an OSPF or eBGP default. Verify with
show ip route 0.0.0.0/0 that the static block has lost its best
marker while the primary is up.
The floating static never activates
The reverse symptom, and usually not a distance problem at all. If the primary route is still in the RIB, the backup is correctly staying out of the FIB — the question is why the primary has not been withdrawn.
Diagnostic order:
show ip route <prefix>— is the primary still there? Then the protocol has not withdrawn it, and the backup is behaving correctly.- Is the failure one the protocol can see? A dark fibre drops the link and OSPF withdraws in seconds. A far-side failure that leaves the local link up does not, until the protocol’s dead interval expires.
- If sub-second failover is the requirement, distance is not the
mechanism. Attach BFD to the primary —
set protocols static route 0.0.0.0/0 next-hop 192.0.2.1 bfdfor a static primary, or BFD on the OSPF or BGP session — so the withdrawal happens on a timer you control.
A static route is ignored where a connected route exists
A connected route is distance 0 and a static cannot go below 1, so the
static will never be selected for a prefix the connected route already
covers exactly. show ip route shows it present and not best.
This is not a bug to work around; it is the router refusing to believe a typed statement over an observed link. If the traffic really must leave by a different path, the answer is a more specific prefix (longest-prefix match runs before distance and will win), or policy routing, not a distance edit.
Two equal-distance statics are load-sharing when one was meant as backup
Two set protocols static route statements for the same prefix, both
at the default distance 1, produce an ECMP pair rather than a
primary and a standby. Flows hash across both, and half of them go out
the path that was never meant to carry traffic.
There is no metric to separate them (see the callout above). Give the
standby an explicit higher distance — that is the whole fix, and it
is the reason the distance leaf exists on a per-next-hop basis.
A prefix is arriving over iBGP when it should come from the IGP
iBGP is 200 and every IGP is below it, so this usually means the IGP
is not offering the prefix rather than that BGP is beating it.
Check show ip route <prefix> for an OSPF or IS-IS candidate at all
before reaching for a distance override; if there is none, the fault
is in the IGP’s advertisement, and lowering BGP’s internal distance
would only hide it.
Validation
The sequence for “the wrong route won”:
- Confirm the prefix.
ip route get <destination>— establish which prefix is actually matching, because a longest-prefix-match surprise looks exactly like a distance surprise from the outside. - List the candidates.
show ip route <prefix>— every routing entry, every distance, and thebestmarker. - Name the winner’s source. The
Known viastring, not a guess from the next-hop address. - Compare against the table above. If the distance printed is not
the documented default, something in the configuration overrode it;
show configuration commands | match distancefinds it. - Check the kernel agrees.
ip route show <prefix>should show the candidate thatshow ip routemarkedbest. A disagreement is a zebra-to-kernel installation failure, which is a different and more serious problem than a selection surprise. - Decide whether the expectation or the configuration was wrong. Both are common. A route that lost to a lower distance behaved correctly, whatever the change ticket said it should do.
Cross-course references
- Part II’s lesson on longest-prefix match covers the comparison that runs before distance, and the failure where an operator blames distance for an LPM outcome.
- Part XII’s lessons on static routes cover the full attribute set on
set protocols static route, including BFD and blackhole routes. - Part XXXVI’s ECMP lessons cover what happens when candidates tie on distance instead of one winning.
- Part XXXIX’s multi-WAN lessons cover distance as an active-passive control and the three mechanisms it is one of.
Quiz
Knowledge check · 4 questions
Q1. The backup ISP link is carrying production traffic even though the primary is healthy. Explain what selected it, and fix the configuration.
R1 learns a default route from the core over OSPF: `set protocols ospf default-information originate always` R1 also has a floating static default pointing at a cheap backup circuit: `set protocols static route 0.0.0.0/0 next-hop 198.51.100.1 distance 100` The static was intended as a backup. Monitoring shows the OSPF adjacency up and the core reachable, but egress traffic is leaving over the backup circuit and the ISP is billing overage.
Q2. A static route and an OSPF route both cover 10.20.0.0/16. The static is at the default distance. The OSPF route has a cost of 20. Which does zebra install, and why?
Q3. A static route can never displace a connected route for the same prefix on VyOS 1.5.
Q4. A backup static default is permanently beating the DHCP-learned default from the primary ISP. Explain the two distances involved and correct the design.
eth0 is the primary ISP handoff and is DHCP-addressed: `set interfaces ethernet eth0 address dhcp` The operator adds a backup default through a second ISP on eth1: `set protocols static route 0.0.0.0/0 next-hop 198.51.100.1` After the commit, all egress traffic leaves via eth1. The DHCP lease on eth0 is current and the primary ISP is up.
Passing score: 75%. Answers are checked in this browser.
Production discipline
Administrative distance is one number per routing source, compared
once per prefix, in one process. Learn the defaults, read the real
number off show ip route rather than recalling it, and treat every
override as something that needs a written reason attached to it.
Distance is not a tuning knob — it is the router’s statement about
which of its informants it believes, and changing it changes that
belief everywhere at once.