Showing results for 
Search instead for 
Did you mean: 
Cisco Employee
Cisco Employee


In this document I'll discuss the operation, use and some examples on RPL, or the route policy language.


Route policies are mandatory for E-BGP peers, at least a "pass-all" like RPL is required in order to import and export routes.


Core Issue

In IOS we used to have route-maps to control the import, export and manipulation of routes. IOS-XR doesn't have route-maps but something more powerful called route policy language. It is a very programmatic approach in route-maps.


Where as IOS route-maps operate as a series of statements which are executed sequentially, Route-policies not only operate sequentially but provide the ability to invoke other route-policies much like a ‘C’-program is able to call separately defined functions. This enables to creation of hierarchical policies. In addition, and most importantly into respect the scope of this paper, route-policies are ‘compiled’ into a run-time executable portion of code.

Editing route policies

When you have configured a route policy that you want to edit afterwards, you need to restart from scratch or copy paste the existing RPL as entering the route-policy configuration would wipe the existing one out:


RP/0/RSP0/CPU0:A9K-BNG(config)#route-policy test

RP/0/RSP0/CPU0:A9K-BNG(config-rpl)#if med eq 100 then

RP/0/RSP0/CPU0:A9K-BNG(config-rpl-if)#set local-preference 100







RP/0/RSP0/CPU0:A9K-BNG(config)#route-policy test

Fri Jan 20 14:58:39.900 EDT

% WARNING: Policy object route-policy test' exists! Reconfiguring it via CLI wil

l replace current definition. Use 'abort to cancel.



RP/0/RSP0/CPU0:A9K-BNG(config-rpl)#if local-preference eq 123 then

RP/0/RSP0/CPU0:A9K-BNG(config-rpl-if)#set origin incomplete




RP/0/RSP0/CPU0:A9K-BNG(config)#do sh run route-policy test

Fri Jan 20 14:59:53.705 EDT

route-policy test

  if local-preference eq 123 then

    set origin incomplete





As you can see the previous if statement is completely gone, copy pasting and offline editing are also not very easy to use! There is a solution!


RP/0/RSP0/CPU0:A9K-BNG#edit route-policy test ?

  emacs  to use Emacs editor

  nano   to use nano editor

  vim    to use Vim editor



I tend to prefer VI and then you can edit your RPL in a VI like manner:


Editting screen:


route-policy test

  if local-preference eq 123 then

    set origin incomplete

  else if med eq 100 then

    set weight 44







I am inserting the bold italic lines and press "ZZ" to exit and save the VI editor. (Note I made a config error in RED)




"/dev/shmem/rpl_edit.115790135" 8 lines, 149 characters written

Proceed with commit (yes/no/cancel)? [cancel]:



Now the config error here by splitting "else if" and look what happens when I try to commit:



149 bytes parsed in 1 sec (148)bytes/sec


% Syntax/Authorization errors in one or more commands.!! SYNTAX/AUTHORIZATION ER

RORS: This configuration failed due to

!! one or more of the following reasons:

!!  - the entered commands do not exist,

!!  - the entered commands have errors in their syntax,

!!  - the software packages containing the commands are not active,

!!  - the current user is not a member of a task-group that has

!!    permissions to use the commands.


  else if med eq 100 then

    set weight 44




Continue editing? [no]:yes


"/dev/shmem/rpl_edit.115790135" 8 lines, 145 characters written

Proceed with commit (yes/no/cancel)? [cancel]: yes


145 bytes parsed in 1 sec (144)bytes/sec


Prepared commit in 0 sec


1 items committed in 1 sec (0)items/sec

Updating.RP/0/RSP0/CPU0:Jan 20 15:04:20.101 : config[65848]: %MGBL-CONFIG-6-DB_COMMIT : Configuration committed by user 'root'. Use 'show configuration commit changes 1000000522' to view the changes.


Updated Commit database in 1 sec



So from now one when you want to edit RPL's, prefix sets or as-sets or community sets, use this editor


RP/0/RSP0/CPU0:A9K-BNG#edit ?

  as-path-set       edit an as-path-set

  community-set     edit a community-set

  extcommunity-set  edit an extended-community-set

  policy-global     edit policy-global definitions

  prefix-set        edit a prefix-set

  rd-set            edit a rd-set

  route-policy      edit a route-policy



RPL operation






RPL Actions

The route policy requires a "ticket" for the route to be accepted or dropped. These are the different operatators


Pass – prefix allowed if not later dropped

pass grants a ticket to defeat default drop

Execution continues after pass

Set – value changed, prefix allowed if not later dropped

Any set at any level grants a ticket

Execution continues after set

Values can be set more than once

Done – prefix allowed, stop execution

Drop – prefix is discarded

Explicit drop stops policy execution

Implicit drop (if policy runs to end without getting a ticket)


One thing important to add is here that if you have a policy that is "sequential" like

if med 10 then

 set med 20


if med 20 then



the execution will NOT drop prefixes with MED10. The reason for that is, although somewhat counter intuitive, that the sequence of operation uses the ORIGINAL value during processing, hence the second if statement will not match for the what was original med of 10...

If you like to get the behavior that both 10 and 20 are dropped, you could do something like this:

if med 10 then drop

else if med 20 then drop

else pass


Don't forget the final pass, as there is an implicit deny.


Hierachical policies

The ability to reference one policy in another


route-policy one


     set weight 100






route-policy two


     set med 200






route-policy three


    apply two


    set community (2:666) additive






route-policy four


    apply one


    apply three







Parameter Passing

The ability to call one policy with a variable to be used in another policy:


route-policy one ($med)


  set med $med






route-policy two


  apply one (10)




Or with 2 variables:


route-policy three ($med,$origin)


  set med $med


  set origin $origin






route-policy four


  apply three (10, incomplete)




Inline vs. Named sets

In your RPL you can put the prefix set or as-path etc in the IF statement construction or you can reference a separate set with the AS-list.

They look like the following:




route-policy use_inline


  if as-path in (ios-regex '_42$', ios-regex '_127$') then















as-path-set named_set


  ios-regex '_42$',


  ios-regex '_127$'





route-policy use_named


if as-path in named_set then












There is a performance difference between teh two. the Named Set is obviously slightly slower, but is easier to manage especially when the list gets long. I would personally recommend for short lists to use inline and for longer lists to use the named-set.


Each individual set element results in a separate call to the expression engine:


as-path-set as_51

ios-regex ‘_2129$’,

ios-regex ‘_2147$’,

ios-regex ‘_2856$’,

ios-regex ‘_3486$’,

ios-regex ‘_6432$’,

ios-regex ‘_6468$’,

ios-regex ‘_7310$’,

ios-regex ‘_7768$’,

ios-regex ‘_7862$’,

ios-regex ‘_8296$’



The same set can be written as follows:


as-path-set as_51

ios-regex '_(2129|2147|2856|3486|6432|6468|7310|7768|7862|8296)$'


Example AS-Path-Set, Community-Set and Prefix-Set




as-path-set aset1


    ios-regex ’_42$’,


    ios-regex ’_127$’






prefix-set galaga, ge 16 le 30






community-set cset1










•Match by value, wildcard, or regular expression
•2 16 bit values separated by colons
•Support for common community keywords








Show commands

show bgp policy route-policy <name>

Only display prefixes matching policy – filter show command


RP/0/0/CPU0:XR#show rpl route-policy states

ACTIVE -- Referenced by at least one policy which is attached

INACTIVE -- Only referenced by policies which are not attached

UNUSED -- Not attached (directly or indirectly) and not referenced



Working with Prefix-Sets


Here some examples of using prefix-sets. The use of the variable masks is not easy to understand and I found the CCO documentation not very explanatory, so here a few extra words on that.


Prefix:                                        Explanation:,                match only one possible value,, mask omitted means 32.,             match only one possible value, ge 28,       match a range of prefix values, from to le 28,       match a range of values, from to (eg we can’t “reach” the last 4 bits) ge 26 le 30, matches prefixes in the range from to eq 28        match any prefix of length 28 in the range from through ge 16 le 24, matches any prefix of length 32 in the range 10.0.[0..255].2/32 (from to This is a little funky given the “7” in the 3rd octet which effectively    becomes don’t care. ge 8 le 16   matches any prefix of length 26 in the range 10.[0..255].8.0/26 (from to



Let me visualize it with some real outputs.

I am using an RPL that sets the local pref to 1234 if it matches the prefix set, and that prefix set is as per the above sample list. ge 28,             match a range of prefix values, from to

=> What is excluded here ?  Is excluded from the prefix range ?


Whether the .128 is excluded or not, depends on the mask of the prefix being advertised.

Basically what this means is that if the mask of the route is larger or equal than 28 (so 29,30,31,32) then it matches:


   Network            Next Hop            Metric LocPrf Weight Path


*>i10.0.3.0/28                100   1234      0 2 3 {4} i

*>i10.0.3.16/28                100   1234      0 2 {3,4} i

*>i10.0.3.32/28                100   1234      0 2 3 {4,5} i

*>i10.0.3.48/28                100   1234      0 2 i

*>i10.0.3.0/26                100    300      0 2 3 {4} i

*>i10.0.3.64/26                100    300      0 2 {3,4} i

*>i10.0.3.2/31                100   1234      0 2 {3,4} i

*>i10.0.3.4/31                100   1234      0 2 3 {4,5} i

*>i10.0.3.6/31                100   1234      0 2 i

*>i10.0.3.0/24                100    300      0 2 3 {4} i le 28,             match a range of values, from to (eg we can’t “reach” the last 4 bits)

=> What is excluded here ?, .2, .3, .17, .18,.19,.20, etc?


Same as before, but now where the mask is less than 28, so routes in the 10.0.4.x range that have a mask that is shorter 28 will get “hit”.

The mask on the prefix itself sets the “base”. Eg 10.0.3 would not match here as it is not part of the Seems obvious but just to be clear ...


   Network            Next Hop            Metric LocPrf Weight Path

*>i10.0.4.0/24                100   1234      0 2 3 {4} i

*>i10.0.4.0/26                100   1234      0 2 3 {4} i

*>i10.0.4.64/26                100   1234      0 2 {3,4} i

*>i10.0.4.128/26                100   1234      0 2 3 {4,5} i

*>i10.0.4.48/28                100   1234      0 2 i

*>i10.0.4.64/28                100   1234      0 2 3 {4,5} i

*>i10.0.4.24/30                100    300      0 2 3 i

*>i10.0.4.28/30                100    300      0 2 {3} i ge 26 le 30,       matches prefixes in the range from to

Combining the previous two together on the .5.0 range:


*>i10.0.5.4/30                100   1234      0 2 {3,4} i

*>i10.0.5.8/30                100   1234      0 2 3 {4,5} i

*>i10.0.5.12/30                100   1234      0 2 i

*>i10.0.5.4/31                100    300      0 2 3 {4,5} i

*>i10.0.5.6/31                100    300      0 2 i

*>i10.0.5.5/32                100    300      0 2 3 {4,5,6} i

*>i10.0.5.6/32                100    300      0 2 3 i

*>i10.0.5.0/25                100    300      0 2 3 {4} i

*>i10.0.5.128/25                100    300      0 2 {3,4} i

*>i10.0.5.64/26                100   1234      0 2 {3,4} i

*>i10.0.5.128/26                100   1234      0 2 3 {4,5} i ge 16 le 24,      matches any prefix of length 32 in the range 10.0.[0..255].2/32 (from to This is a little funky given the “7” in the 3rd octet which effectively becomes don’t care.


*>i10.0.7.2/32                100   1234      0 2 3 {4} i

*>i10.0.7.3/32                100    300      0 2 {3,4} i

*>i10.0.0.2/32                100   1234      0 2 3 {4} i

*>i10.0.0.3/32                100    300      0 2 {3,4} i

*>i10.1.7.2/32                100    300      0 2 3 {4} I <<doesn’t match because of 2nd octet


If I slightly change the prefix statement to: ge 16 le 24


*>i10.0.7.0/30                100    300      0 2 3 {4} i

*>i10.0.7.4/30                100    300      0 2 {3,4} i

*>i10.0.7.8/30                100    300      0 2 3 {4,5} i


Still no match as the base mask is not met on the prefixes received.

So the /<whatever> determines the MASK of the route I wanted to match. whereas the GE/LE provide me the variance in either that mask (if bigger) or from the other octects (if smaller then the /mask)




Verifying performance of your RPL


To determine what in your route-policy is consuming the majority of the time, you can use route profiling.

It allows some data collection in the background with minimal impact  on the execution of the rpl. After the collection has been running for  some time you can use show commands to find out which steps take a lot  of time in the execution and make some improvements.

Once we figure out which portion of the policy is performance drag, its much easier to try out an alternative. Something like regex match always failing means we need to evaluate route using prefix match prior to validating its as-paths.


Example usage:

debug pcl profile detail


Router# show pcl protocol bgp 10 neighbor-in-dflt default-IPv4-Uni- policy profile

Policy execution profile


Protocol : bgp 10


Attachpoint : neighbor-in-dflt


AP Instance : default-IPv4-Uni-


Policy Name : rpl_profile(nexthop)


Pass : 10


Drop : 5


Total : 15


Avg execution time : 110usec




Router#sh rpl route-policy rpl_profile detail


route-policy test


  apply test2








route-policy test2

  delete extcommunity rt all





route-policy rpl_profile($p_nexthop)

  if next-hop in $p_nexthop then
    set local-preference 155

    set med 155



    set local-preference 77

    set med 77



  set community (0:0)

  apply test

  set extcommunity rt (1:1)




Router# show pcl protocol bgp 10 neighbor-in-dflt default-IPv4-Uni- policy profile detail

Policy execution profile


Protocol : bgp 10


Attachpoint : neighbor-in-dflt


AP Instance : default-IPv4-Uni-


Policy : rpl_profile(nexthop)


Pass : 15


Drop :  0


Total : 15


Avg execution time : 110usec



Node Id   Num visited  Avg exec time  Policy operation


           15          0usec                    route-policy rpl_profile


PXL_0_5            15         99usec                        if next-hop pfxmatch ... then


PXL_0_3            10          0usec                              set local-preference 155
PXL_0_4            10          0usec                              set med 155
PXL_0_6            15          0usec                              community assign
                            15          0usec                           route-policy test


                            15          0usec                                       route-policy test2


PXL_0_1            15          0usec                                                rt delete-all
                            15          0usec                                            


PXL_0_2            15          0usec                                         


PXL_0_8             0          0usec                              rt assign
                             0          0usec                                




PXL_0_1             5          0usec                                          set local-preference 77
PXL_0_2             5          0usec                                          set med 77



GOTO :                                                                                    PXL_0_6







                            0          0usec                     






Usable attachpoints for RPL




Changing or modifying Route policies (or prefix/community sets)


As you have noticed when editting RPL's you need to reconfigure the complete policy in the regular CLI. An easier method is using the "edit" option described above.

When you are changing your RPL or prefix-set or any other list that RPL is using, it will trigger a few things:

If the RPL is used for BGP and your peer is not REFRESH capable, it will restart your BGP session.

If the peer is REFRESH capable a full table refresh is executed.

The reason for that is, that the RPL change or say prefix set change could have excluded some routes before that now may need to be imported.


On the Receiving Side:

For BGP, routes that are filtered are completely discarded and are NOT kept in memory with some kind of mark that says bgp rpl filtered.

We will use route refresh to obtain the routes again from the neighbor whenever there is a change in inbound route policy.

For this the neighbor has to be refresh capable, else we have to do clear bgp.


When the BGP peer receives a route refresh request it sends the complete table again to the requesting peer. While asking for the table they ask for the relevant (AFI, SAFI) table. When the routes are received from the peer an inbound filter if any is applied and the routes are aggregated.


On the sending side:

if I apply an RPL basically removing some previously advertised route, would BGP send withdraws for these now filtered routes?

What would rpl/bgp do when the RPL is modified to:

           1) do advertise some previously filtered routes

To advertise previously filtered routes it is similar to regular advertising of routes

           2) stop advertising previously advertised routes

BGP will send withdraws when it stops advertising previously filtered routes.






Xander Thuijs, CCIE #6775

Sr. Tech Lead ASR9000

Michael Macek


I find suspicious behavior of RPL  delete community  command, policy applied on BGP ingress.

RPL example:

set community (1:1,2:2) additive

delete community in (1:*)

Result is route with community 2:2 but I would expect 1:1,2:2

Based on documentation all attribute check should be based on original attributes, not modified/new (valid at least for 'if'), but seems that delete works with  both original and new communities.

IOS XR 5.3.4, ASR9K, RSP880

Best regards


Cisco Employee
Cisco Employee

It is working properly.

Actions work on exsiting and changed attributes. 

Conditional matching uses only original attributes.

HTH, Brad 


Hi Smail,

Have you been able to find solution for your requirement? I have been searching for this currently too. If you have found solution, I will be very happy to know the solution. Juniper has a very easy solution as you know, if XR has this solution it would be great.



Cisco Employee
Cisco Employee

under the vrf definition's address-family, you can do a route-target import to pull in the prefixes from the other vrf's RT.

that doesnt work?

and correct, the next hop is inherited from the other vrf, it would say

vrf x:

prefix/mask next-hop <that next hop> (found in vrf y)



Hi Rajendra,

Yes I did! Jakob Heitz helped me a lot, so follow his example. 

What version are you running? I believe that you need 6.1.2+ for make it to work because of a new feature that was introduced.

It's "export to vrf allow-imported-vpn" under VRF config.

If you are stuck please reply and we will try to help you out.


Hi Smail/Xander,

Thanks a lot for recommendations. Working on Smails suggestion. Thumbs up. Also as Xander is referring on next hop case, it will be applicable for networks beyond the p2p ip. I have some requirements where I need connected routes to be leaked between vrfs. Or like say in BNG, if some subscribers routes need to be shared between vrf, how can we do that? since it is learned as "subscriber". I have faced this issue using CGNAT.

In juniper its very easy using rib-groups where I can share any routes of any protocol between 2 vrfs.




Hi Rajendra,

you can redistribute subscriber routes the same way like it's with static or connected routes.

Under BGP address family configure "redistribute subscriber route-policy SET_COM_101" Do not redistribute subscriber routes! You could kill the device. Create a summary static route and use the same approach i.e. redistribute static route-polici SET_COM_101.

Using RPL you can decide for which prefixes you want to set community. Using RPL you can achieve what ever you want.

RPL should look like this:

route-policy SET_COM_101
set community (101:101)

Under VRF config configure conditional export

vrf XYZ
export route-policy EXPORT_SUBSCRIBER

RPL config:

if community matches-any (101:101)  then
set extcommunity rt (65101:50)  --- This community should be imported under the VRF where you want to import the routes.
delete community in (101:101)



I did a quick edit of my previous post. I am replying so that you get a notification.


Hi Smail,

Thanks for the help. I solved it using your reference. You guys are great.

Thumbs up !!!





Presume I have an existing RPL where I am not aware of the number of IF/ELSE statements within it.

For example:

if TEST-1 then
 set SOMETHING to "A"
elseif TEST-3 then
 set SOMETHING to "C"
elseif TEST-4 then
 set SOMETHING to "D"
elseif TEST-24 then
 set SOMETHING to "X"


I dont want to rewrite the entire RPL appending my new statement appropriately into this RPL.


Is there some way I can insert an IF/ELSE statement into this RPL?

for example:

elseif TEST-2 then
 set SOMETHING to "B"


If yes,

1. How can I insert this at the start of this RPL?

2. How can I insert this at the end on an RPL?

3. How can I insert this at the "n"th position of an RPL?


Thanks in advance for your response.




Hello Xander,

Wonder if it is correct place to ask for SR related stuff, but it is also RPL related.

I need to apply "set label-index" on route-policy to or from BGP LU neighbor, but 6.1.2 is complaining that "" 

 !!% Policy [BSID] uses the 'label-index' attribute. There is no 'label-index' attribute at the bgp neighbor-out-dflt attach point. ""


Segment Routing book Part I also states on page 241 that at the time of writing of the book XR can only set Prefix-SID when originating the route.


Official config guide says:


A routing policy with the set label-index attribute can be attached to a network configuration or redistribute configuration. Other routing policy language (RPL) configurations are possible. For more information on routing policies, refer to the "Implementing Routing Policy" chapter in the Cisco ASR 9000 Series Aggregation Services Router Routing Configuration Guide.


What are the options of setting Prefix-SID attribute on router which is NOT the originator of the route (no redistribute, no network)?





Jon Berres

Hey Xander,


Great article as always. Question on BGP route injection. I have a scenario where our upstream peer only accepts /128 IPv6 host routes. I need to match conditionally on a /64 network inside an L3vpn and then inject the /128 to my eBGP peer. Is there a clean way of doing this in XR? 







Is it possible to pass a route-policy name as a parameter of another route-policy, to apply different route policies according to this parameter? I would like to achieve something like this (on incoming policy for ebgp peer):


route-policy RPL_EGBP_PEER_IN($peer_type,$peer_as,$lp)

apply $peer_type

set community (64555:$peer_as)

set local-preference $lp





Edit: looks like it works if I specify exact route-policy name as $peer_type parameter. Is it possible to set up some aliases between parameter value and route-policy name? I would like to use some other $peer_type value, not an exact route-policy name. For example, if I specify $peer_type = big, I would like to apply a route policy RPL_UPLINK_BIG, or if I specify $peer_type=full, then it should refer to policy RPL_UPLINK_FULL etc.




Hello again,

Is it expected behavior that "done" statement in child policy also stops execution of a parent policy? Example:

route-policy PARENT

apply CHILD

set community COMM1

set local-preference LP



I have condition in CHILD policy with"done" statement, and if it matches then execution stops and does not return to PARENT policy for set statements.




Maybe a newbie question, but I am in need of a route-policy whereby I specify a number of /32s and I want to divert only their udp/53 to a specific next-hop.  Everything else flows normally.


What I have so far is:


route-policy Diversion
if destination in Prefixes then
set next-hop
prefix-set Prefixes eq 32, eq 32


How do I add in that I only want to divert udp/53 to a route-policy?  If not possible via route-policy - what commands in IOS-XR could I use to accomplish this?  Not ABF since this isn't in ingrres but rather on egress.



Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community:

Recognize Your Peers
Quick Links