VyOSXIV · Multiple Routing TablesRouting tables
Routing table troubleshooting — ip route show table all, ip rule show, asymmetry
What you'll learn
- Run the canonical troubleshooting command set for a multi-table deployment
- Use ip route get to validate the RPDB walk for a specific source and destination
- Detect asymmetric routing with two-direction traceroute and source-binding
- Diagnose missing routes, unreferenced tables, and rule priority errors
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
Routing table troubleshooting — ip route show table all, ip rule show, asymmetry
A multiple-routing-table deployment is one of the easiest to
misconfigure and one of the hardest to debug if the operator
does not know the right command set. The routes exist; the rules
exist; the configuration committed; but the packet does not
follow the path the operator expected. The cause is usually one
of three things: a rule that points at the wrong table, a
table that has no matching route, or an asymmetric return path.
This lesson covers the troubleshooting command set that exposes
all three, the ip route get validation that confirms the
intended RPDB walk, and the asymmetry-detection pattern that
catches the most common production failure.
The troubleshooting command set
flowchart TD
A[Multi-table incident] --> B[Local view]
A --> C[Forward path]
A --> D[Return path]
B --> B1[ip rule show]
B --> B2[ip route show table all]
B --> B3[ip route get]
B --> B4[show ip rule]
B --> B5[vtysh -c 'show ip rule']
C --> C1[traceroute -s <src> <dst>]
C --> C2[tcpdump -ni <iface>]
D --> D1[traceroute from destination]
D --> D2[looking glass query]
The local view is what the local kernel and FRR know. The forward path is what the Internet actually carries for traffic from a representative source. The return path is what arrives back from the destination. The operator must check all three to localise a multi-table incident.
The local view — ip rule and ip route show table all
The first command is ip rule show. It lists every rule in the
kernel’s RPDB:
vyos@vyos:~$ ip rule show
0: from all lookup local
100: from 10.10.0.0/24 lookup isp-a
200: from 10.20.0.0/24 lookup isp-b
32766: from all lookup main
32767: from all lookup default
The walk order is priority ascending. For any given packet, the kernel evaluates the rules in this order; the first matching rule determines the table.
The second command is ip route show table all. It lists the
routes in every table:
vyos@vyos:~$ ip route show table all
table local:
local 192.0.2.1 dev lo proto kernel scope host src 192.0.2.1
broadcast 192.0.2.255 dev lo proto kernel scope link src 192.0.2.1
table main:
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
table isp-a:
default via 198.51.100.1 dev eth0 proto static metric 1
198.51.100.0/24 dev eth0 proto kernel scope link src 198.51.100.2
table isp-b:
default via 203.0.113.1 dev eth1 proto kernel scope link src 203.0.113.2
table default:
This is the canonical inventory of what the kernel knows. The operator should compare the inventory against the design expectations: every custom table should have routes; every referenced table should have at least one rule; every rule should have a matching table with matching routes.
The VyOS shell shows the same data through show ip rule and
show ip route:
vyos@vyos:~$ show ip rule
0: from all lookup local
100: from 10.10.0.0/24 lookup isp-a
200: from 10.20.0.0/24 lookup isp-b
32766: from all lookup main
32767: from all lookup default
The VyOS view and the kernel view should agree. If they do not, the cause is a script that bypassed VyOS or a failed commit that left the live state inconsistent.
The local view — ip route get
The third command is ip route get <dst> from <src>. It performs
the full RPDB walk for the specified source and destination and
returns the table, the next-hop, and the egress interface:
vyos@vyos:~$ ip route get 8.8.8.8 from 10.10.0.5
8.8.8.8 from 10.10.0.5 via 198.51.100.1 dev eth0 table isp-a uid 0
cache
This is the most precise validation. The operator can issue the command from the router with any source address and confirm the table the kernel would consult, the next-hop it would use, and the interface it would egress on. If the output does not match the design, the rule chain is wrong.
ip route get is also useful with the iif parameter:
vyos@vyos:~$ ip route get 8.8.8.8 from 10.10.0.5 iif eth2
The iif parameter overrides the input interface selection and
forces the RPDB walk to start as if the packet arrived on
eth2. This is useful when the operator wants to validate the
walk for a specific ingress without actually generating traffic.
The forward path — traceroute -s
The forward path validation is traceroute -s <src> <dst> from
a host on the corresponding LAN. The -s option forces the
source address; the host sends the probe packets with the
specified source.
host-a:~$ traceroute -s 10.10.0.5 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max
1 198.51.100.1 (198.51.100.1) 0.456 ms
2 198.51.100.1.isp-a.net 4.234 ms
3 ...
4 8.8.8.8
The first hop is the ISP-A gateway. If the first hop is the ISP-B gateway, the source-based routing is not working — either the rule is wrong, the route is in the wrong table, or the return-path asymmetry is causing the connection to fail despite the correct forward path.
A second traceroute -s <src> from a host on LAN-B confirms
the ISP-B egress:
host-b:~$ traceroute -s 10.20.0.5 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max
1 203.0.113.1 (203.0.113.1) 0.498 ms
2 ...
3 8.8.8.8
The two traceroute outputs must show different first hops —
one ISP-A gateway, one ISP-B gateway. If both show the same
gateway, the source-based routing is broken at the local level.
The return path — asymmetry detection
The return path validation is the most important troubleshooting
step the operator often skips. The forward path is tested by
traceroute -s from the source LAN; the return path must be
tested by traceroute from the destination back to the source.
remote-host:~$ traceroute 10.10.0.5
traceroute to 10.10.0.5 (10.10.0.5), 30 hops max
1 203.0.113.1 (203.0.113.1) 0.412 ms <- ISP-B!
2 ...
3 10.10.0.5
The return path goes via ISP-B, but the forward path went via ISP-A. The routing is asymmetric. A stateful device on either path sees only one direction of the flow; the connection is broken.
The detection is two traceroute runs:
host-a:~$ traceroute -s 10.10.0.5 8.8.8.8
1 198.51.100.1 (ISP-A)
host-b:~$ traceroute -s 10.20.0.5 8.8.8.8
1 203.0.113.1 (ISP-B)
remote-host:~$ traceroute 10.10.0.5
1 203.0.113.1 (ISP-B) <- mismatch
remote-host:~$ traceroute 10.20.0.5
1 198.51.100.1 (ISP-A) <- mismatch
If the return paths are swapped relative to the forward paths, the routing is asymmetric. The fix is upstream — BGP, source- address binding, or negotiated return routes — not at the local router.
Common failure modes — diagnosis
The production failure modes the engineer must recognise:
- Missing route in custom table.
ip route show table isp-ashows no default.ip route get 8.8.8.8 from 10.10.0.5returns the wrong table (falls through tomain). Fix: install the default in the custom table. - Rule priority wrong.
ip rule showshows the custom rule at priority 32768 instead of 100. The walk order meansmainis consulted first. Fix: lower the priority. - Source selector wrong.
ip rule showshowsfrom 10.10.0.0/24but the LAN is10.10.0.0/16. Fix: correct the prefix. - Table referenced but no routes. The rule references
isp-a; the table has no routes; the lookup misses; the walk falls through. Fix: install routes in the table. - Return-path asymmetry.
traceroute -sexits via ISP-A, buttraceroutefrom the destination returns via ISP-B. Fix: upstream — BGP announcement, source-address binding, or negotiated return routes. - Router-originated traffic fails. BGP sessions from the
router fail. The router’s source address is not in any custom
rule. Fix: add a default in
mainor a rule for the router’s source. - Alias missing.
ip route show table <name>returnsInvalid argument. The rt-table declaration is missing or malformed. Fix: declare the alias inset system ip rt-table.
The post-incident evidence package
A multi-table incident that goes to a post-incident review must have an evidence package. The package includes:
ip rule show— the kernel RPDB at the time of the incident.ip route show table all— the full route inventory across every table.show ip rule(VyOS view) — the configuration-derived view.show configuration system ipv4 rule— the rules in the configuration tree.show configuration system ip rt-table— the rt-table declarations.show configuration protocols static— the static routes (in themaintable by default; in custom tables if configured).ip route get <dst> from <src>— the RPDB walk output for the affected traffic.traceroute -s <src> <dst>from the source LAN — the forward path.traceroutefrom the destination — the return path./var/log/frr/zebra.log— the zebra log for the affected period.- The change request or commit log for the affected deployment.
- The timestamp of the incident and the timestamp of the recovery.
The evidence package is what the next operator reads. A good evidence package is reproducible — the next operator can run the same commands on a similar incident and find the same evidence.
How it fails
The production failure modes the engineer must recognise:
- Configuration not committed. The operator set the rules
and routes in
configuremode but did notcommit. Theshow configurationshows the changes;ip rule showdoes not. Fix:commit; save. - Configuration not saved. The operator committed but did
not save. A reboot reverts to the saved config; the custom
tables and rules disappear. Fix:
save. - Script bypassed VyOS. A startup script added rules and
routes outside of VyOS. The kernel sees them; FRR does not.
After a
commit; saveand reload, the script’s state is lost. Fix: remove the script and add the configuration to VyOS. - Table ID collision. The operator declared a custom table at an ID that a VRF is already using. The commit fails with an error; the configuration is in the candidate but not active. Fix: choose a different ID.
- Wrong interface in connected route. The static route in
the custom table has
interface eth0but the egress should beeth1. The route installs; the egress is wrong. Fix: correct the interface.
Rollback
The recovery from a multi-table incident depends on the failure mode. The canonical rollbacks:
- Wrong rule:
delete system ipv4 rule <priority>; commit; save. - Wrong route in custom table:
delete protocols static table <name> route <prefix>; commit; save. - Wrong rt-table declaration:
delete system ip rt-table rt-table-id <id>; commit; save. - Whole-tree rollback:
rollback N; commit; save.
For emergency rollback, load <file>; commit; save replaces the
candidate with a saved backup. For live-state rollback (a script
that bypassed VyOS), the operator must remove the offending
state with ip rule del and ip route del and re-apply the
correct configuration through VyOS.
Production discipline
Cross-course references
The Linux course’s XXII-Linux-NetTroubleshoot covers the host-
side equivalent of the troubleshooting command set. The PBR
course’s XIII-VyOS-PBR covers the policy-routing troubleshooting
in the broader sense. The BGP course’s XXXI-BGP-Troubleshooting
covers route-selection failures that affect multi-table
deployments where BGP provides the return path.
Quiz
Knowledge check · 4 questions
Q1. Which command on VyOS 1.5 LTS performs the full RPDB walk for a specific source and destination and returns the table the kernel would consult?
Q2. On a VyOS 1.5 LTS router, an operator can validate the local rule chain with `traceroute -s <src> <dst>` from a host on the source LAN.
Q3. After deploying source-based routing, an operator runs `ip route get 8.8.8.8 from 10.10.0.5` and the output shows `table main` instead of `table isp-a`. The rule at priority 100 is `from 10.10.0.0/24 lookup isp-a`. What is the most likely cause?
The RPDB walks rules in priority order; for traffic from 10.10.0.5, the rule at priority 100 should match and select `isp-a`. If `ip route get` returns `main`, the rule is either not being consulted, the selector does not match, or the lookup in `isp-a` is missing and the walk falls through to `main`. The operator must check the rule's selector, the table's contents, and the priority.
Q4. An operator configures source-based routing. `ip route get` returns the correct table and egress interface. `traceroute -s` from the source LAN shows the correct first hop. But TCP connections from hosts on the source LAN time out. What is the next troubleshooting step?
The local rule chain is correct; the forward path is correct. The return path is the next thing to validate. The operator must run `traceroute` from the destination back to the source to confirm the return path matches the forward path. If the return path goes via a different ISP, the connection is asymmetric.
Passing score: 75%. Answers are checked in this browser.