VyOSXXXIII · Route PolicyRoute-map composition
Route-map composition — match and set clauses, sequence ordering, implicit deny
What you'll learn
- Configure a route-map with match and set clauses on VyOS 1.5 LTS
- Predict the AND/OR semantics of multi-clause match statements
- Use set clauses to manipulate BGP attributes (community, local-preference, metric, as-path prepend, next-hop)
- Recognise the implicit-deny on no-match and design a route-map that is auditable
Prerequisites
- Ethernet, MAC and ARP — the Layer 2 the routing engineer must read
- Policy concept — the vocabulary, the building blocks, the evaluation order
- 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
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
The route-map is the policy primitive that does two things no other primitive can: it matches a route against multiple criteria, and it manipulates the route’s attributes. Every BGP neighbour policy, every redistribution filter, and every complex policy decision in production is implemented with a route-map.
On VyOS 1.5 LTS the route-map is composed of numbered rules;
each rule has an action (permit or deny), one or more
match clauses, and zero or more set clauses. The route-map
evaluates rules top-to-bottom by sequence; the first rule that
matches the route decides the disposition; later rules are
not consulted.
This lesson covers the match and set semantics, the sequence ordering, and the implicit-deny behaviour that distinguishes route-maps from prefix-lists.
Anatomy of a route-map rule
A route-map rule has four parts:
- sequence number — positive integer that orders the rule in the route-map. Lower numbers evaluate first.
- action —
permit(apply set clauses, continue to next route) ordeny(do not apply set clauses, route is filtered). - match clause — one or more criteria the route must satisfy for the rule to fire. The criteria combine with AND across types and OR within a type.
- set clause — one or more attribute manipulations applied
to the route when the rule fires. Set clauses are only
applied if the rule’s action is
permit.
set policy route-map OSPF-TO-BGP rule 10 action permit
set policy route-map OSPF-TO-BGP rule 10 match ip address prefix-list INTERNAL-NETWORKS
set policy route-map OSPF-TO-BGP rule 10 match community FROM-IGP
set policy route-map OSPF-TO-BGP rule 10 set metric 100
set policy route-map OSPF-TO-BGP rule 10 set community 64512:400 additive
This rule:
- Has sequence 10, action
permit. - Matches routes whose prefix is in the
INTERNAL-NETWORKSprefix-list AND whose community is in theFROM-IGPcommunity-list. - On a match, sets the metric to 100 and adds the community
64512:400to the route’s community-set (additive).
flowchart TB
R["Route\nprefix, AS_PATH, community, ..."]
L1{"Sequence 10\nmatches?"}
L2{"Sequence 20\nmatches?"}
L3{"Sequence 30\nmatches?"}
P10["Action permit\nApply set clauses\nRoute continues"]
D10["Action deny\nRoute is filtered"]
P20["Action permit\nApply set clauses\nRoute continues"]
D20["Action deny\nRoute is filtered"]
X["Implicit deny\n(no rule matched)\nRoute is filtered"]
R --> L1
L1 -->|"yes, action permit"| P10
L1 -->|"yes, action deny"| D10
L1 -->|"no"| L2
L2 -->|"yes, action permit"| P20
L2 -->|"yes, action deny"| D20
L2 -->|"no"| L3
L3 -->|"yes, action permit"| P30
L3 -->|"yes, action deny"| D30
L3 -->|"no"| X
The first matching rule wins. If no rule matches, the implicit-deny applies: the route is filtered.
Match semantics — AND across types, OR within type
A route-map rule with multiple match clauses combines them with AND across types and OR within a type:
- AND across types —
match ip address prefix-list FOOANDmatch community BARmeans the route must satisfy both: the prefix must be inFOOAND the community must matchBAR. If either fails, the rule does not fire. - OR within type —
match ip address prefix-list FOOandmatch ip address prefix-list BAZon the same rule (if supported by the configuration tree) mean the route’s prefix must be inFOOorBAZ. The VyOS configuration tree typically allows onematch ip addressper rule; the operator who needs OR uses two rules with different sequences.
flowchart TB
R["Route\nprefix: 10.0.0.0/16\ncommunity: 64512:100 64512:200"]
M1["match ip address prefix-list INTERNAL\nmatches: 10.0.0.0/16 (yes)"]
M2["match community FROM-IGP\nmatches: 64512:100 (yes)\nor 64512:200 (yes)\n=> permit (any-community semantic)"]
AND["AND across types:\nboth M1 AND M2\n=> rule fires"]
P["Action permit\nset metric 100\nset community 64512:400 additive"]
R --> M1
R --> M2
M1 --> AND
M2 --> AND
AND -->|"both true"| P
The OR-within-type applies to community-lists (any community
on the route matches), as-path access-lists (the AS_PATH
matches the regex), and prefix-lists with ge or le (the
prefix is in the range).
Set clauses — what the rule does to the route
A set clause writes an attribute back to the route. The set
clauses are only applied if the rule’s action is permit (a
deny action does not apply set clauses; the route is
filtered).
The common set clauses on VyOS 1.5 LTS:
# Metric (BGP MED)
set policy route-map ... set metric <value>
# Local preference (iBGP only)
set policy route-map ... set local-preference <value>
# AS path prepend (BGP)
set policy route-map ... set as-path prepend <AS> [<AS> ...]
# Community (additive: adds to existing community-set;
# non-additive: replaces the community-set)
set policy route-map ... set community <AA:NN> [additive]
set policy route-map ... set community none
# Next-hop (eBGP)
set policy route-map ... set ip next-hop <IP>
set policy route-map ... set ip next-hop peer-address
# Origin (BGP)
set policy route-map ... set origin igp
set policy route-map ... set origin incomplete
set policy route-map ... set origin egp
# Weight (Cisco-style, VyOS exposes it as a BGP-specific option)
set policy route-map ... set weight <value>
The additive keyword on set community is critical: it
adds the community to the route’s existing community-set;
without additive, the community-set is replaced. The
operator who forgets additive strips every community the
upstream peer added — including the well-known no-export
that was protecting downstream peers.
Sequence ordering and the implicit deny
The route-map evaluates rules top-to-bottom by sequence number. The first rule that matches the route (the match clauses evaluate to true) decides the disposition:
- If the rule’s action is
permit, the set clauses are applied; the route is permitted; later rules are not consulted. - If the rule’s action is
deny, the set clauses are NOT applied; the route is filtered; later rules are not consulted.
If no rule matches the route, the implicit deny applies: the route is filtered.
The implicit deny at the end of a route-map is the opposite of the implicit deny in a prefix-list. A prefix-list that falls off the end denies the route; a route-map that falls off the end also denies the route. But the semantics differ:
- A prefix-list with no explicit permit denies everything (the implicit deny is the safety net).
- A route-map with no explicit permit denies everything (the implicit deny is the default behaviour).
The difference shows up when the operator writes a route-map with a deny rule followed by an implicit deny. The deny rule matches explicitly; the implicit deny catches everything else. The behaviour is the same as a prefix-list with an explicit deny at the end.
# Production pattern: deny bad, permit good
set policy route-map FROM-PEER-A rule 10 action deny
set policy route-map FROM-PEER-A rule 10 match ip address prefix-list BLOCK-LIST
set policy route-map FROM-PEER-A rule 20 action permit
set policy route-map FROM-PEER-A rule 20 match ip address prefix-list ALLOW-LIST
# No rule 30 or higher — implicit deny catches everything else
The operator who writes only deny rules and expects the rest to be permitted is wrong. The route-map falls off the end and the implicit deny applies. The defensive idiom is to write a catch-all permit at the end (rule 100 or higher).
Operational commands
# The configured route-map
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 is the canonical
validation: it shows every route that the route-map processed
and the set clauses that were applied. The operator who has
just written a new rule should run this command to confirm
the rule is firing on the intended routes and not firing on
unintended routes.
Failure modes
Multi-clause match with one clause failing
The operator writes a rule with two match clauses. The route matches the first clause but not the second. The AND across types means the rule does not fire. The route falls through to the next rule (or the implicit deny).
Diagnostic:
vtysh -c 'show route-map <name>'shows the hit count for the rule is zero (or lower than expected).show ip bgp route-map <name>does not include the expected routes.
Fix: simplify the match (one clause), or add another rule that matches the second clause alone.
set community without additive strips communities
The operator writes set community 64512:400 without
additive. The community-set is replaced with 64512:400.
The receiving peer loses the original communities.
Diagnostic:
show ip bgp <prefix>shows the community-set is just64512:400. The original communities are gone.
Fix: change to set community 64512:400 additive.
Catch-all permit missing; route-map filters everything
The operator writes a route-map with permit rules but no catch-all permit. The implicit deny at the end filters every route that does not match a permit rule. The redistribution becomes a blackhole.
Diagnostic:
show ip bgpshows no routes (or only the ones that matched a permit rule).show ip routeshows the routes are not in the RIB.
Fix: add a catch-all permit at the end of the route-map.
Sequence reordering breaks the rule
The operator writes rule 10 permitting INTERNAL-NETWORKS
and rule 20 denying EXCEPTIONS. The operator later inserts
rule 15 permitting NEW-INTERNAL. The matching engine
walks 10 → 15 → 20. The new rule 15 fires before the deny.
Routes that were supposed to be denied by rule 20 are
permitted by rule 15.
Diagnostic:
- Routes that should be denied are permitted.
show policy route-mapshows the new rule 15 is more general than rule 20’s match.
Fix: reorder so the deny fires before the permit, or make rule 15’s match more specific.
Rollback
A route-map change is reversible through the standard VyOS mechanisms:
rollback Nandcommitto revert to a previous configuration revision.delete policy route-map <name>andcommitto remove the route-map. The referencing BGP neighbour or redistribution is left dangling; the commit validator catches this.delete policy route-map <name> rule <seq>andcommitto remove a single rule.set policy route-map <name> rule <seq> action permit(override the deny) to permit everything during a debugging window — restore after.
The VyOS commit validator rejects a BGP neighbour or redistribution that references a missing route-map.
Production discipline
Cross-course references
XIII-VyOS-PBR(vyos-xiii-02-route-maps) covers route-maps in the policy-based-routing context. The match and set semantics are the same.XXV-VyOS-BGPAdvertise(vyos-xxv-03-bgp-redistribute-static,vyos-xxv-04-bgp-redistribute-ospf) shows route-maps in the BGP redistribution context.XXVI-VyOS-BGPAttributescovers the BGP attributes that route-maps manipulate: community, local-preference, as-path prepend.
Quiz
Knowledge check · 4 questions
Q1. A route-map rule has `match ip address prefix-list FOO` and `match community BAR`. A route matches FOO but does not match BAR. What is the disposition?
Q2. A `set community 64512:400` clause without `additive` adds the community to the route's existing community-set.
Q3. An operator writes a route-map with rule 10 denying routes in prefix-list BLOCK-LIST and rule 20 permitting routes in 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. After the commit, 5 routes are in the BGP table. What happened?
The route-map is: rule 10 deny BLOCK-LIST, rule 20 permit ALLOW-LIST. The peer sends 100 routes. The 45 routes that are in neither list do not match any rule.
Q4. An operator writes a route-map rule with `set community 64512:400` (no `additive`) intending to tag routes from the IGP. The upstream peer stamps the routes with `no-export` to prevent leakage. After the commit, `show ip bgp` shows the routes are advertised to the downstream peer (no longer protected by `no-export`). Why?
The route-map is applied inbound from the IGP redistribution. The set clause is `set community 64512:400` (no additive). The routes had `no-export` from the upstream peer.
Passing score: 75%. Answers are checked in this browser.