BGP · · 4 min read

BGP Route Maps: Matching, Setting, and Manipulating Paths

Prefix lists filter routes by address and mask length. But BGP policy often needs more — matching on AS-path patterns, community values, or MED, and then changing attributes to influence path selection. Route maps provide this full match-and-set capability, making them the primary tool for BGP traffic engineering on Cisco IOS XE.

Route Map Structure

A route map is an ordered list of clauses, each with a sequence number, a permit/deny action, match conditions, and set actions:

route-map NAME {permit|deny} SEQ
 match CONDITION
 set ACTION

Common Match Conditions

! Match by prefix list
match ip address prefix-list PL-NAME

! Match by AS-path (using a regex in an as-path access-list)
match as-path AS-PATH-ACL-NUMBER

! Match by community
match community COMMUNITY-LIST-NAME [exact-match]

! Match by MED
match metric 100

! Match by next-hop
match ip next-hop prefix-list NH-LIST

! Match by route source (advertising peer)
match ip route-source prefix-list PEER-LIST

Common Set Actions

! Set local preference (iBGP path selection)
set local-preference 150

! Set MED (influence neighbor's inbound path)
set metric 50

! Set weight (local to this router only)
set weight 200

! Set community
set community 65001:100 additive

! Prepend AS-path
set as-path prepend 65001 65001

! Set next-hop
set ip next-hop 10.1.1.1

! Set origin
set origin igp

Applying Route Maps to BGP Neighbors

router bgp 65001
 neighbor 172.16.0.2 route-map ISP-A-IN in
 neighbor 172.16.0.2 route-map ISP-A-OUT out

Real-World Policy Examples

Example 1: Prefer ISP-A for Specific Prefixes, ISP-B for Everything Else

ip prefix-list PARTNER-NETS seq 10 permit 100.64.0.0/18
ip prefix-list PARTNER-NETS seq 20 permit 100.64.64.0/18
!
route-map ISP-A-IN permit 10
 match ip address prefix-list PARTNER-NETS
 set local-preference 200
!
route-map ISP-A-IN permit 20
 set local-preference 90
!
route-map ISP-B-IN permit 10
 match ip address prefix-list PARTNER-NETS
 set local-preference 90
!
route-map ISP-B-IN permit 20
 set local-preference 200
!
router bgp 65001
 neighbor 172.16.0.2 route-map ISP-A-IN in
 neighbor 172.16.0.6 route-map ISP-B-IN in

Partner networks (100.64.0.0/18, 100.64.64.0/18) get local-pref 200 via ISP-A and 90 via ISP-B — so they route through ISP-A. Everything else gets the inverse — local-pref 200 via ISP-B, 90 via ISP-A.

Example 2: Tag Routes with Communities on Inbound

ip as-path access-list 10 permit ^65010$
ip as-path access-list 20 permit ^65010_
!
route-map TAG-ISP-A permit 10
 match as-path 10
 set community 65001:100 additive
!
route-map TAG-ISP-A permit 20
 match as-path 20
 set community 65001:200 additive
!
route-map TAG-ISP-A permit 30

Routes originated by ISP-A (AS-path is exactly "65010") get community 65001:100. Routes that ISP-A learned from others (AS-path starts with "65010 " followed by more) get 65001:200. Everything else passes through clause 30 unmodified. You can then use these communities for outbound filtering or further policy decisions.

Example 3: AS-Path Prepending on Outbound

route-map PREPEND-TO-ISP-B permit 10
 set as-path prepend 65001 65001 65001
!
router bgp 65001
 neighbor 172.16.0.6 route-map PREPEND-TO-ISP-B out

This makes routes advertised to ISP-B appear 3 hops longer, discouraging ISP-B's upstream from sending traffic through this path. See BGP AS-Path Prepending for when this works and when it doesn't.

AS-Path Access Lists

Route maps often match on AS-path patterns using regular expressions:

! Match routes originated by AS 65010
ip as-path access-list 10 permit ^65010$

! Match routes transiting AS 65010
ip as-path access-list 20 permit _65010_

! Match routes with AS-path length of exactly 1
ip as-path access-list 30 permit ^[0-9]+$

! Match any route (empty regex matches everything)
ip as-path access-list 99 permit .*

Regex key characters: ^ = start, $ = end, _ = any delimiter (space, start, end), . = any character, * = zero or more of the preceding, + = one or more.

Continue Statement

Normally, once a route matches a clause, evaluation stops. The continue statement lets you chain clauses — useful for applying multiple set actions conditionally:

route-map COMPLEX-POLICY permit 10
 match ip address prefix-list CRITICAL-NETS
 set local-preference 200
 continue 20
!
route-map COMPLEX-POLICY permit 20
 match as-path 10
 set community 65001:500 additive
!
route-map COMPLEX-POLICY permit 30

A critical-net prefix originated by AS 65010 gets both local-pref 200 (from clause 10) AND community 65001:500 (from clause 20). Without continue, evaluation would stop at clause 10.

Verification

R1-HQ# show route-map ISP-A-IN
route-map ISP-A-IN, permit, sequence 10
  Match clauses:
    ip address prefix-lists: PARTNER-NETS
  Set clauses:
    local-preference 200
  Policy routing matches: 0 packets, 0 bytes
route-map ISP-A-IN, permit, sequence 20
  Match clauses:
  Set clauses:
    local-preference 90
  Policy routing matches: 0 packets, 0 bytes

R1-HQ# show ip bgp neighbors 172.16.0.2 | include route-map
  Route map for incoming advertisements is ISP-A-IN
  Route map for outgoing advertisements is *not set*

Troubleshooting

SymptomCauseFix
All routes dropped after applying route-mapMissing a final permit clause — implicit deny blocks everything not explicitly matchedAdd an empty permit clause at the end (e.g., route-map NAME permit 999) to pass unmatched routes through.
Set action not taking effectRoute matching a different clause than expected (earlier sequence number)Check show route-map [name] and verify match conditions per clause. Move specific matches to lower sequence numbers.
Route-map applied but BGP table unchangedChanges require a soft reset to take effectRun clear ip bgp [peer] soft in (inbound) or clear ip bgp [peer] soft out (outbound).

Key Takeaways

Read next

© 2025 Ping Labz. All rights reserved.