VyOSII · Routing FundamentalsRouting primitives
Connected routes — the free routes the interface gives you
What you'll learn
- Describe how the kernel automatically installs connected routes for every interface IP
- Explain why connected routes have administrative distance 0 and cannot be overridden
- Diagnose connectivity issues caused by a connected route that should not exist
- Recognise the failure modes that arise when interfaces are added, removed, or reconfigured
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
When an interface on a VyOS router comes up with an IP address, the kernel automatically installs a connected route for the subnet the IP belongs to. The connected route has administrative distance 0 — the most trusted source — and cannot be overridden by any static or dynamic route.
The operator who understands connected routes plans their network with them in mind. The operator who does not spends hours debugging why a “should work” static route is silently ignored.
This lesson is the operator’s foundation in connected routes: how they are installed, why they have AD 0, and the production failure modes that arise from them.
How connected routes are installed
When an interface is brought up with an IP address, the kernel adds three entries to the local routing table:
flowchart TB
subgraph "eth0 with 192.0.2.50/24"
A["Connected route\n192.0.2.0/24 dev eth0\nproto kernel scope link src 192.0.2.50"]
B["Local route\n192.0.2.50/32 dev eth0\nproto kernel scope host src 192.0.2.50"]
C["Broadcast route\n192.0.2.255/32 dev eth0\nproto kernel scope link src 192.0.2.50"]
end
A -->|"packet to 192.0.2.X"| F["Forwarded on eth0"]
B -->|"packet to 192.0.2.50"| L["Delivered locally"]
C -->|"packet to 192.0.2.255"| BRO["Broadcast on eth0"]
The three entries are:
- Connected route (
192.0.2.0/24) — matches any destination within the subnet. Forwards the packet out the interface. - Local route (
192.0.2.50/32) — matches the router’s own IP. Delivers the packet locally (the kernel passes it up the stack). - Broadcast route (
192.0.2.255/32) — matches the subnet broadcast. Broadcasts the packet on the interface.
These three entries are part of the local routing table (table 255). They exist as long as the interface has the IP address. When the IP is removed or the interface goes down, the kernel removes them.
Why connected routes have AD 0
The Linux kernel assigns administrative distance 0 to connected routes because the kernel itself installed them. The kernel is the most trusted source of routing information — it knows the interface is up, it knows the IP is configured. No static route, no dynamic protocol, no human operator is more trustworthy than the kernel’s own view of the interface.
The consequence: a static route to the same prefix is silently ignored. The kernel installs the connected route; the static route is not installed; the operator sees no error message.
configure
# These are both set:
set interfaces ethernet eth0 address 192.0.2.50/24
set protocols static route 192.0.2.0/24 next-hop 198.51.100.1
commit
save
exit
show ip route 192.0.2.0/24
The output:
S > 192.0.2.0/24 [1/0] via 198.51.100.1, eth1
C 192.0.2.0/24 is directly connected, eth0
Wait — both routes are shown, with > marking the static as
selected. But the static and the connected cover the same
prefix. Which one wins?
The kernel installs both, but the lookup uses longest-prefix
match first. With identical prefixes, AD is consulted. The
connected route has AD 0; the static has AD 1. The connected
route wins for traffic to 192.0.2.50 (the router’s own IP,
caught by the local table) but the static can still be the
forwarding path for traffic to other IPs in 192.0.2.0/24 —
no, wait, that’s wrong too. Let me check the kernel behaviour
precisely.
Actually, the Linux kernel installs the connected route in
table local (255) and the static in table main (254). The
kernel’s lookup walks the tables in numeric order. The local
table is consulted first. For any destination within
192.0.2.0/24 other than the router’s own IP, the local
table does not have a match (the local entry is /32 for the
router’s own IP). The lookup falls through to the main table.
Both routes are in the main table. AD comparison: connected (0)
wins over static (1).
So the connected route wins for every destination in
192.0.2.0/24, not just 192.0.2.50. The static route is
installed but never used. The operator’s static route was a
configuration error — they thought they were configuring a
route to 198.51.100.0/24, not 192.0.2.0/24, but the typo
went undetected.
Secondary IP addresses and connected routes
A single interface can have multiple IP addresses. Each IP address generates its own set of connected, local, and broadcast routes.
configure
set interfaces ethernet eth0 address 192.0.2.50/24
set interfaces ethernet eth0 address 198.51.100.65/27
commit
save
The kernel installs:
ip route show
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.50
192.0.2.50/32 dev eth0 proto kernel scope host src 192.0.2.50
198.51.100.64/27 dev eth0 proto kernel scope link src 198.51.100.65
198.51.100.65/32 dev eth0 proto kernel scope host src 198.51.100.65
The router can now send and receive traffic on either IP. The connected routes are independent. There is no “primary” address.
The operator who removes a secondary IP must remove the connected route automatically — the kernel does this when the IP is removed. The operator who adds a secondary IP must remember that any other router sending traffic to the new IP must have a route to it. The connected route on R1 does not propagate to R2 — R2 needs its own route to the new IP.
Connected routes in IPv6
IPv6 connected routes follow the same pattern, with a wrinkle.
IPv6 has no broadcast, so there is no broadcast route. The
link-local address (fe80::/10) is added as a connected route
automatically and is the source of every IPv6 routing-protocol
session on the segment.
show ipv6 route
fe80::/64 dev eth0 proto kernel metric 256
2001:db8:abcd:1::/64 dev eth0 proto kernel metric 256
The link-local is critical. Without it, IPv6 routing protocols cannot establish sessions (BGP, OSPFv3, etc.) because they expect to source their packets from a link-local address. The operator who disables IPv6 link-local on a routing interface breaks every IPv6 routing protocol on that interface.
Connected routes and the firewall
The firewall on VyOS operates at Layer 3 and above. The connected route tells the kernel which packets are destined for the router itself (the local route) versus which are destined for transit (the connected route). The firewall’s input chain handles packets destined for the router; the forward chain handles transit packets.
flowchart LR
P["Packet to 192.0.2.50"] --> L1{"Local table\nlookup"}
L1 -->|"/32 match"|L1a["Input chain\n(terminate locally)"]
L1 -->|"no match"|L1b{"Main table\nlookup"}
L1b -->|"192.0.2.0/24 connected"|L1c["Forward chain\n(transit)"]
L1b -->|other|L1d["Other route\n(forward via next-hop)"]
The firewall rules are applied to the appropriate chain based on the route lookup. A rule in the input chain never affects transit traffic; a rule in the forward chain never affects local traffic. The operator who writes “allow all inbound” in the input chain thinking it covers everything has misread the firewall semantics.
Failure modes
Connected route wins over a more-specific static
The connected route has AD 0. A static route to the same prefix has AD 1. The static is silently ignored.
Diagnostic: ip route get <dst> returns the connected route. ip route show <prefix> shows both, but the connected is selected.
Connected route still active after the IP was “removed”
The operator removes the IP from the configuration but the
connected route persists. This happens when the operator
removes the address via set interfaces ethernet eth0 address
but does not commit — the old configuration is still active.
Diagnostic: show configuration | match "address" shows the new configuration; ip addr show dev eth0 shows the old IP.
Connected route on a sub-interface when the parent is down
A sub-interface (VLAN) has a connected route even when the parent interface is administratively down. The connected route is bound to the sub-interface’s existence, not the parent.
Diagnostic: ip link show dev eth0 shows parent down; ip link show dev eth0.10 shows sub-interface still up; ip route show <subnet> shows the connected route.
Connected route collides with a redistribution
The operator redistributes connected routes into BGP. The connected route on a transient interface (e.g. a dial-up backup) flaps the BGP advertisement. The fix is redistribution filters that match only the intended connected prefixes.
Diagnostic: vtysh show ip bgp shows the prefix; the BGP update history shows the prefix flapping.
Operational commands
The operator verifies connected routes with:
show ip route
show ip route 192.0.2.0/24
ip route show type local
ip route show table local
ip -br addr
show interfaces ethernet eth0
The ip route show type local filter shows only local entries.
The ip route show table local shows only the local table.
Both are useful for confirming that the connected routes exist
and have the right addresses.
Validation
The validation sequence for “the connected route is wrong”:
- The IP exists:
ip addr show dev eth0lists the IPs configured on the interface. - The connected route exists:
ip route show <subnet>shows the connected entry. - The connected route wins:
ip route get <dst>returns the connected route. - The interface is up:
ip link show dev eth0returnsstate UP. - The static / dynamic route exists:
show configuration | match "<prefix>"shows the configured route;vtysh show ip route <prefix>shows what FRRouting knows.
If the connected route wins when it should not, either the IP should be removed from the interface or the more-specific prefix should be different.
Cross-course references
- The Linux course’s
V-Linux-NetConfigcovers the same kernel behaviour from the host perspective. - The lesson on administrative distance in Part II covers AD in depth.
- The lesson on routing tables in Part II covers the field semantics.
Quiz
Knowledge check · 4 questions
Q1. You configure a static route to 192.0.2.0/24 via 198.51.100.1. The interface eth0 has IP 192.0.2.50/24. After commit, `ip route show 192.0.2.0/24` shows both routes. `ip route get 192.0.2.50` returns the connected route. What is the most likely cause and the fix?
R1 has eth0 with 192.0.2.50/24. The operator adds a static route to 192.0.2.0/24 via 198.51.100.1 with the intent of routing 192.0.2.0/24 traffic to a different upstream. After commit, the operator checks the routing table and sees both routes. The static is not selected for traffic to 192.0.2.50.
Q2. A packet arrives at R1 with destination 192.0.2.50 (the router's own IP). Which routing table does the kernel consult first?
Q3. Adding a secondary IP address to R1 creates a connected route on R1 only; R2 still needs a route of its own to reach the new subnet.
Q4. R1 redistributes connected routes into BGP. R1 has a transient backup interface (dial-on-demand) that flaps every 5 minutes. What is the most likely production consequence?
R1 has a backup interface `ppp0` that dials on demand. When connected, R1 redistributes the connected route into BGP. The connected route advertises a small prefix (e.g. 203.0.113.0/24) to the upstream BGP peer. Every time the interface flaps, the BGP advertisement appears or disappears, causing the upstream to install or withdraw the route.
Passing score: 75%. Answers are checked in this browser.
Production discipline
Connected routes are automatic and cannot be overridden. Plan the interface addressing once. Plan the redistribution filters once. Plan the IPv6 link-local once. Then the connected routes either work the way the operator expects, or the operator finds the configuration error before the production incident does.