VyOSXXXIII · Route PolicyPolicy validation
Policy validation — testing with vtysh, clearing route-maps, sequence numbering gotchas
What you'll learn
- Run the vtysh show commands that validate each policy primitive
- Use the clear commands to reset hit counts during testing
- Recognise the sequence-numbering gotchas that cause silent policy bypass
- Build a validation sequence that proves a policy change is correct before commit
Prerequisites
- Ethernet, MAC and ARP — the Layer 2 the routing engineer must read
- Prefix-list — sequence, ge, le, exact-match, deny vs permit
- Community-list — standard, expanded, and regular-expression matching
- AS-path-list — regular-expression matching over the BGP AS_PATH attribute
- Route-map composition — match and set clauses, sequence ordering, implicit deny
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
A policy change that passes validation but does not do what the operator intended is a silent failure. The routes are in the BGP table, the commit succeeded, the configuration is syntactically correct — but the prefix the operator wanted to block is being advertised, or the route the operator wanted to permit is being denied. The operator who validates the policy with the right commands catches these failures before they affect production traffic.
This lesson covers the validation sequence for each policy primitive, the clear commands that reset hit counts during testing, and the sequence-numbering gotchas that cause silent policy bypass.
The validation sequence
The canonical validation sequence after a policy change is:
# 1. The configuration is in the tree (VyOS)
show policy route-map
show policy prefix-list
show policy community-list
show policy as-path-list
# 2. The matching engine has loaded the policy (FRR)
vtysh -c 'show route-map'
vtysh -c 'show ip prefix-list'
vtysh -c 'show bgp community-list'
vtysh -c 'show bgp as-path-access-list'
# 3. The policy is doing what the operator intended
vtysh -c 'show ip bgp route-map <name>'
vtysh -c 'show ip bgp filter-list <name>'
vtysh -c 'show ip bgp community <value> exact-match'
# 4. The hit counts match expectations
vtysh -c 'show route-map <name>' # per-rule hit count
vtysh -c 'show ip prefix-list <name>' # per-rule hit count
# 5. The route-map and prefix-list agree on the same prefix
vtysh -c 'show ip prefix-list <name> <prefix>'
vtysh -c 'show route-map <name> <prefix>' # if supported
If steps 1 and 2 disagree, the configuration has not been committed or the commit failed silently. If steps 2 and 3 disagree, the matching engine is not processing the policy correctly. If steps 3 and 4 disagree, the policy is doing something the operator did not expect.
Validating a prefix-list
# The configured list (VyOS)
show policy prefix-list INBOUND
# The matching engine's view (FRR)
vtysh -c 'show ip prefix-list'
vtysh -c 'show ip prefix-list INBOUND'
# The sequence and hit count per rule
vtysh -c 'show ip prefix-list INBOUND seq 10'
# Test a specific prefix against the list
vtysh -c 'show ip prefix-list INBOUND 192.168.1.0/24'
# Clear the hit counts
clear ip prefix-list
The show ip prefix-list <name> <prefix> command is the
canonical validation. It returns permit or deny for the
prefix against the list. The operator who has just written
a new rule should run this command for every prefix the
rule is supposed to match, and for at least one prefix the
rule is supposed to reject.
The clear ip prefix-list command resets the hit counts.
The operator who is testing a new rule should clear the
counts before the test, run the test traffic, then read the
counts to confirm the rule fired.
Validating a community-list
# The configured list (VyOS)
show policy community-list FROM-PEER-A
# The matching engine's view (FRR)
vtysh -c 'show bgp community-list'
vtysh -c 'show bgp community-list FROM-PEER-A'
# Routes carrying a specific community
vtysh -c 'show ip bgp community 64512:100'
vtysh -c 'show ip bgp community 64512:100 exact-match'
# Routes matching a regex
vtysh -c 'show ip bgp regexp "_64512:.*"'
# Clear the hit counts
clear bgp community-list
The show ip bgp community <value> command returns every
route whose community-set contains <value>. The operator
who has just stamped a new community should run this
command to confirm the community is on the routes.
The clear bgp community-list command resets the hit
counts for testing.
Validating an as-path access-list
# The configured list (VyOS)
show policy as-path-list MY-FILTER
# The matching engine's view (FRR)
vtysh -c 'show bgp as-path-access-list'
vtysh -c 'show bgp as-path-access-list MY-FILTER'
# Routes matching a regex
vtysh -c 'show ip bgp regexp _64513_'
# Routes filtered by the list
vtysh -c 'show ip bgp filter-list MY-FILTER'
# Clear the hit counts
clear bgp as-path-access-list
The show ip bgp filter-list <name> command is the
canonical validation for an as-path access-list. It shows
every route whose AS_PATH was processed by the list. The
operator who has just written a new rule should run this
command to confirm the filter is doing what it claims.
Validating a route-map
# The configured route-map (VyOS)
show policy route-map FROM-PEER-A
# The matching engine's view (FRR)
vtysh -c 'show route-map'
vtysh -c 'show route-map FROM-PEER-A'
# Routes that matched the route-map (and what was applied)
vtysh -c 'show ip bgp route-map FROM-PEER-A'
# Clear the hit counts
clear route-map
The show ip bgp route-map <name> command shows every
route that the route-map processed and the set clauses
that were applied. This is the most informative command
for validating a complex route-map.
The clear route-map command resets the hit counts for
testing.
Sequence-numbering gotchas
The most common production failure modes in policy are sequence-numbering errors. The matching engine walks rules top-to-bottom by sequence; the first matching rule wins; later rules are not consulted. The operator who writes a broad permit rule at a low sequence number catches every route that should have been denied by a specific rule at a higher sequence number.
Gotcha 1: rule 10 is too broad
# Intent: permit INTERNAL, deny EXCEPTIONS
set policy route-map ... rule 10 action permit
set policy route-map ... rule 10 match ip address prefix-list INTERNAL
set policy route-map ... rule 20 action deny
set policy route-map ... rule 20 match ip address prefix-list EXCEPTIONS
A route in EXCEPTIONS that is also in INTERNAL matches rule 10 first (because it is in INTERNAL). The route is permitted. Rule 20 is never consulted. The exception is silently bypassed.
Diagnostic:
show ip bgp route-map <name>shows routes in EXCEPTIONS that should be denied.vtysh -c 'show route-map <name>'shows rule 10 has a hit count and rule 20 has zero hits (or low).
Fix: reorder the rules. Deny first, then permit.
Gotcha 2: the sequence is not what was intended
The operator writes rule 10 intending to permit and rule 20
intending to deny. After a set typo or a copy-paste error,
the rule is at sequence 100 instead of 10. The matching
engine walks 10, 20, 30, …, 100. The deny rule at 100
fires only after every permit rule has been evaluated. A
route that matches a permit rule at sequence 10 is
permitted, even if it should have been denied by the rule
at sequence 100.
Diagnostic:
show policy route-map <name>shows the rule order.vtysh -c 'show route-map <name>'shows the rule order.
Fix: delete the rule and re-create it at the correct
sequence number. VyOS does not support set policy route-map <name> rule <seq> rule <new-seq> (no renumber); the operator
must delete and re-set.
Gotcha 3: the rule’s match clause is not what was
intended
The operator writes match ip address prefix-list INTERNAL
intending to match the prefix. The VyOS configuration tree
parses this correctly. But the operator forgets that
match ip address prefix-list matches the prefix AND the
prefix length (a /24 in the prefix-list does not match a
/16 route). The rule fires only for exact-length matches.
Diagnostic:
show ip bgp route-map <name>does not include the expected routes.vtysh -c 'show ip prefix-list INTERNAL <prefix>'returnsdenyfor the route.
Fix: adjust the prefix-list to match the intended
prefix-length range, or use ge/le to broaden the
match.
Gotcha 4: the rule is referenced but does nothing
The operator writes a route-map with match ip address prefix-list EMPTY-LIST (a prefix-list that has no rules).
Every route falls through to the implicit deny. The
route-map looks correct in the configuration; the operator
who does not test the rule sees no error.
Diagnostic:
vtysh -c 'show ip prefix-list EMPTY-LIST'returns no rules.show ip bgpshows routes that should be permitted are missing.
Fix: add rules to the prefix-list, or reference a different prefix-list.
The clear-route-map sequence
The clear-route-map sequence is the canonical test procedure:
# 1. Clear the hit counts
clear route-map
clear ip prefix-list
clear bgp community-list
clear bgp as-path-access-list
# 2. Trigger a soft reset of the BGP session (re-evaluate
# inbound policy)
clear ip bgp <peer> soft in
# 3. Wait for the BGP session to re-evaluate (a few seconds)
# 4. Read the hit counts
vtysh -c 'show route-map'
vtysh -c 'show ip prefix-list'
vtysh -c 'show bgp community-list'
vtysh -c 'show bgp as-path-access-list'
# 5. Read the routes that were admitted or denied
vtysh -c 'show ip bgp neighbors <peer> routes'
vtysh -c 'show ip bgp filter-list <name>'
vtysh -c 'show ip bgp route-map <name>'
The soft reset triggers the BGP session to re-evaluate the inbound policy against the routes it has already received. This is faster than waiting for a new UPDATE; the routes are re-evaluated in place.
The clear ip bgp <peer> soft in command is non-destructive:
it does not reset the TCP session; it triggers a route
refresh. The peer must support route refresh (RFC 2918); all
modern BGP implementations do.
Rollback
A policy validation failure is rolled back through the standard VyOS mechanisms:
rollback Nandcommitto revert to a previous configuration revision.delete policy <primitive> <name>andcommitto remove the policy.delete policy <primitive> <name> rule <seq>andcommitto remove a single rule.
The validation commands do not modify the configuration; they only display the matching engine’s state. The operator can run them as often as needed without affecting production.
Production discipline
Cross-course references
- The previous lessons in this part (
xxxiii-02-prefix-list,xxxiii-03-community-list,xxxiii-04-as-path-list,xxxiii-05-route-map-composition) cover the policy primitives that this lesson validates. XXXIV-VyOS-Redistribution(lessonsxxxiv-01throughxxxiv-06) uses these validation commands to verify redistribution route-maps.- The Linux course’s
V-Linux-NetConfigcovers the host-side perspective on policy (iptables, nftables).
Quiz
Knowledge check · 4 questions
Q1. After a prefix-list change, which command tests a specific prefix against the list?
Q2. The `clear route-map` command removes the route-map from the configuration.
Q3. An operator writes a route-map with rule 10 denying prefix-list BLOCK-LIST and rule 20 permitting prefix-list ALLOW-LIST. They apply it to inbound from a peer. The peer sends 100 routes; 50 are in ALLOW-LIST, 5 are in BLOCK-LIST, and 45 are in neither. The operator wants to verify the route-map. They run `clear route-map`, then `clear ip bgp <peer> soft in`, then `vtysh -c 'show route-map'`. The hit count for rule 10 is 5, for rule 20 is 50. The hit count for the implicit deny is 45. What does this confirm?
The route-map is rule 10 deny BLOCK-LIST, rule 20 permit ALLOW-LIST. The peer sends 100 routes. After clear + soft reset, the hit counts are: rule 10 = 5, rule 20 = 50, implicit deny = 45.
Q4. An operator writes a prefix-list with rule 10 permitting 10.0.0.0/8 le 16 and rule 20 permitting 10.5.0.0/16. They expect rule 20 to be more specific and 'win' for 10.5.0.0/16. They run `vtysh -c 'show ip prefix-list MYLIST 10.5.0.0/16'` and the output is `permit seq 10`. The operator is confused: rule 20 should have fired. What is wrong?
The list is rule 10 (10.0.0.0/8 le 16 permit) and rule 20 (10.5.0.0/16 permit). The route is 10.5.0.0/16. The expected behaviour: rule 20 fires (more specific). The actual behaviour: rule 10 fires (permit seq 10).
Passing score: 75%. Answers are checked in this browser.