VyOSXII · Static RoutingStatic routing
Static routes — the foundation of a routed estate
What you'll learn
- Explain what a static route is and how the kernel installs it in the FIB
- Configure a static route in VyOS 1.5 LTS with next-hop, interface, distance, and metric
- Validate the route with show ip route and the FRR zebra dataplane
- Recognise the production failure modes that affect static routes
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
Static routes — the foundation of a routed estate
Static routes are the most explicit form of forwarding information. The operator writes the prefix, the next-hop, and optionally the egress interface into the configuration; the router installs the route verbatim; the kernel forwards packets that match the prefix to the stated next-hop. There is no discovery, no negotiation, no convergence. The route is what the operator wrote or it is absent. This lesson covers the static route model in VyOS 1.5 LTS and FRR, the configuration tree, the validation command set, and the production failure modes the operator must recognise.
What a static route is
flowchart LR
A[Packet to 10.20.0.5] --> B[Kernel FIB lookup]
B --> C{Match in table}
C -->|hit| D[Forward to 192.0.2.2]
C -->|miss| E[ICMP unreachable<br/>or default route]
D --> F[Egress interface eth0]
F --> G[Next-hop router]
A static route is a manually-installed entry in the routing information base (RIB). The route consists of a prefix, a next-hop address, an egress interface, an administrative distance, and a metric. The kernel uses the RIB to populate the forwarding information base (FIB) — the data structure consulted on every packet lookup. When a packet arrives, the kernel performs a longest-prefix-match against the FIB and forwards the packet to the next-hop associated with the matching entry.
The set protocols static route tree in VyOS 1.5 LTS places the
configuration under protocols static. The CLI syntax is
modal: prefix, then a sequence of attribute nodes. The
attributes are not mutually exclusive; most production routes
combine them.
The configuration tree
A static route is a single set protocols static route path
with a prefix and zero or more attributes. The minimum
configuration is a prefix and either a next-hop or an interface.
[edit]
vyos@vyos# set protocols static route 10.20.0.0/16 next-hop 192.0.2.2
[edit]
vyos@vyos# commit
[edit]
vyos@vyos# save
The command installs a route to 10.20.0.0/16 with next-hop
192.0.2.2. The egress interface is not specified; the kernel
performs a recursive lookup to find the egress interface from
the next-hop’s connected route. This is the canonical “indirect”
static route form.
The direct form combines a next-hop and an interface:
[edit]
vyos@vyos# set protocols static route 10.20.0.0/16 next-hop 192.0.2.2 interface eth0
[edit]
vyos@vyos# commit
[edit]
vyos@vyos# save
The interface is explicit. This is the “direct” static route form. It is appropriate on point-to-point links (where the interface implies the neighbour) and on Ethernet segments where the next-hop is on the same L2 segment.
The interface-only form omits the next-hop:
[edit]
vyos@vyos# set protocols static route 10.20.0.0/16 interface eth1
[edit]
vyos@vyos# commit
[edit]
vyos@vyos# save
This is appropriate on point-to-point interfaces where the neighbour is implied by the link. The kernel creates a connected route to the peer and forwards the packet to the peer. The interface-only form is a “proxy ARP” style of forwarding that is less common in modern VyOS deployments.
Distance and metric
The administrative distance controls which routing source wins when two sources advertise the same prefix. The metric controls preference within a routing source. For static routes, the defaults are:
- Distance: 1 (more preferred than any dynamic protocol, less preferred than connected at 0).
- Metric: 0 (the default; static routes do not participate in metric-based preference within the static routing source).
A static route with distance 1 is the most preferred static. A static route with distance 210 sits behind BGP (which uses distance 20 for eBGP, 200 for iBGP), OSPF (110), and IS-IS (115), but ahead of any external redistribution. This is the “floating static” pattern covered in the next lesson.
[edit]
vyos@vyos# set protocols static route 10.20.0.0/16 next-hop 192.0.2.2 distance 210
[edit]
vyos@vyos# commit
[edit]
vyos@vyos# save
The distance 210 makes the route inactive while a higher- precedence route is present. When the higher-precedence route withdraws, the floating static becomes active. This is the standard pattern for an OSPF-or-BGP-primary static-backup failover.
The metric field is accepted but does not influence selection between static routes. It is preserved in the FIB for tools that read the metric (e.g. routing policy that matches on metric). A production static route rarely needs a non-zero metric.
[edit]
vyos@vyos# set protocols static route 10.20.0.0/16 next-hop 192.0.2.2 metric 100
[edit]
vyos@vyos# commit
[edit]
vyos@vyos@vyos# save
How the result is validated
The validation command set is layered. Each layer shows a different view of the same route.
vyos@vyos:~$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - table, v - VNC, V - VNC-Direct, A - Babel,
D - SHARP, F - PBR, f - OpenFabric,
> - selected route, * - FIB route
S>* 10.20.0.0/16 [1/0] via 192.0.2.2, eth0, 00:00:12
C>* 192.0.2.0/24 is directly connected, eth0
The show ip route output shows the route as S (static)
with distance 1, metric 0, next-hop 192.0.2.2, interface
eth0. The * in the second column means the route is in
the FIB. The > means it is the selected route for the
prefix.
The show ip route static filter is useful when the table is
large:
vyos@vyos:~$ show ip route static
S>* 10.20.0.0/16 [1/0] via 192.0.2.2, eth0
S>* 172.16.0.0/12 [210/0] via 10.0.0.2, eth1
The first route is the active primary. The second is a
floating backup (distance 210) that is inactive while any
higher-precedence route for 172.16.0.0/12 exists.
The kernel view is the source of truth for the FIB. The FRR
zebra daemon writes the route into the kernel through netlink;
the kernel exposes the same route through the ip command:
vyos@vyos:~$ ip route show
10.20.0.0/16 via 192.0.2.2 dev eth0 proto static metric 1
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.1
The proto static confirms the route was installed by the
static routing source. The metric 1 is the kernel’s view of
the distance. The ip route show output must agree with
show ip route; if it does not, the route is in FRR but not
in the kernel, and traffic to the prefix will fall back to a
less-specific route (or to the default route, or to ICMP
unreachable).
How it fails
The production failure modes the engineer must recognise:
- Route not in FRR. The
commitsucceeded but the route is not in FRR’s configuration. The cause is a mis-typed prefix or a validation rule that silently rejected the change. Checkshow configuration protocols staticand look for the route. - Route in FRR but not in the kernel. A
setthat triggered a zebra error. Theshow ip routeshows the route, butip route showdoes not. Check the FRR logs in/var/log/frr/zebra.log. - Recursive next-hop unreachable. An indirect static route
whose next-hop does not have a connected route. The route
appears as
inactiveinshow ip route. The kernel cannot resolve the egress interface. - Wrong egress interface. A direct static route pointing to the wrong interface. The packet is forwarded to the wrong segment; the next-hop does not see the frame.
- Distance wrong. A backup route with distance 1 is permanently active; a primary route with distance 210 is permanently inactive. The two routes are in conflict, the distance decides which wins.
- Prefix overlap. A
10.0.0.0/8static and a10.20.0.0/16static. Both are installed. The more-specific wins for10.20.x.xtraffic, the less-specific for everything else in10.x.x.x. The operator expected only the more-specific.
Rollback
The recovery from a bad static route configuration:
- Wrong prefix:
delete protocols static route <prefix>; commit; save. - Wrong next-hop:
set protocols static route <prefix> next-hop <correct>; commit; save. - Wrong distance:
delete protocols static route <prefix> distance; commit; save(back to the default 1). - Whole-tree rollback:
rollback N; commit; saveto revert to a known-good revision.
For emergency rollback, the candidate configuration can be
replaced with load <file>; commit; save where <file> is a
saved backup.
Production discipline
Cross-course references
The Linux course’s V-Linux-NetConfig covers the
ip route host-side equivalent. The OPNsense course’s
XII-OPNsense-StaticRoutes covers the equivalent FRR-managed
static routing on the OPNsense platform. The BGP course’s
XXXI-BGP-Troubleshooting covers route selection where static
and BGP both advertise the same prefix.
Quiz
Knowledge check · 4 questions
Q1. Which command confirms that a static route is in the kernel FIB, not just in the FRR RIB?
Q2. A static route with distance 210 is more preferred than a static route with distance 1.
Q3. An operator configures a static route to 10.20.0.0/16 with next-hop 192.0.2.2. The `show ip route` shows the route but `ip route show` does not. What is the most likely cause?
The route is in FRR's RIB but the kernel has not installed it. The zebra daemon is supposed to push the route through netlink. The mismatch indicates a zebra error or a kernel-level rejection.
Q4. An operator configures two static routes to 10.20.0.0/16, one with next-hop 192.0.2.2 (distance 1) and one with next-hop 192.0.2.3 (distance 1). The router only installs the first. What is the expected behaviour?
Two static routes with the same prefix and the same administrative distance. FRR treats them as a multi-path (ECMP) candidate set and installs both. With one egress interface and two next-hops, the router will load-share between them.
Passing score: 75%. Answers are checked in this browser.