Route filters are one of the match criteria in Junos policy. It is a way of matching against a single route or a group of routes. Route filters consist of a prefix to match against, what style of match should be made, and can optionally have an action defined.
In some ways, route filters are similar to prefix lists, but route filters have more match types and can have an action directly associated with them.
The general form of a router filter is:
route-filter <prefix>/<prefix-length> <match-type> <actions>
Actions are an optional setting, and if none are specified the ‘then’ clause of the policy term will be used.
Policy created using route filters can be simple to read and understand, or made quite complex by the interaction of multiple router filters within a single term.
How Routes Are Matched Against A Route Filter
When using a route filter, the match is made in two parts. First, the route is compared to the prefix and prefix length on a longest-match basis. This is important where more than one route filter is defined within a policy term. Once this longest prefix match is made, it then evaluates the match type. To be matched, a route must be matched against both the longest prefix match and the match type.
In a policy term with multiple route filters, once a route has matched against one route filter by the longest prefix match step, it cannot be evaluated against the other route filters in the term, even if it fails the match-type part of the matching process.
Note: We’ll return to this later, as this behavior can be changed.
Match Types
For the following explanations, assume that the prefix and prefix length are 172.16.0.0/16
The available match types are:
Exact – The route must have the same prefix length. This would mean a route of 172.16.0.0/16 will match, but any 172.16.0.0 route with a longer prefix will not.
Longer – The prefix length of the route must be longer than the prefix specified. This would mean 172.16.0.0/16 would not match, but anything longer will. For example 172.16.0.0/20 or 172.16.200.0/24
Orlonger – The prefix length of the route can be equal to or longer. You can think of this as combining the exact and longer match types.
Prefix-length-range – Allows you to specify a range of prefix lengths to match on. If this was set to /23 – /26 then any route from the 172.16.0.0/16 supernet with a prefix length of between 23 and 26 would match. 172.16.0.0/24, 172.16.1.128/25, and 172.16.200.0/23 are all examples of prefixes that would match.
Upto – Matches from the specified prefix up to the prefix length you specify. So 172.16.0.0/16 upto /24 will match all routes in 172.16.0.0/16 up to a prefix-length of /24
The ‘through’ and ‘address-mask’ match types won’t be covered in this post as they are not commonly used.
Basic Route Filter Examples
This first batch of examples shows the basic use of route filters and the match conditions. The BGP peer will have one import policy applied, and that policy will be shown with each example.
All of the following examples are based on the vMX-1 receiving the following routes:
lab@vMX-1> show route protocol bgp terse
inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.0.0/12 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.0.0/16 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.0.0/22 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.0.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.1.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.1.128/25 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.1.192/26 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.1.224/27 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.2.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.3.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/16 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/22 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.1.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.2.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.3.0/24 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
lab@vMX-1>
Example 1 – Route Filter Using Exact Match
In this example, we match exactly on a specific route and accept it. All other routes are rejected by the term named final.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.20.0.0/16 exact;
}
then accept;
}
term final {
then reject;
}
[edit]
lab@vMX-1#
As you can see from the following show route command, only the 172.20.0.0/16 route is present. This is because it is the only route that matches both the prefix and length (172.20.0.0/16) and the match type (exact). Because the route filter did not have a terminating action associated with it, the ‘then’ clause of the term‘test’ accepted the route.
The other routes, which do not match the route filter are matched by the term ‘final’ and rejected. Note that because the term final does not have a ‘from’ clause, it matches all routes.
[edit]
lab@vMX-1# run show route protocol bgp terse
inet.0: 23 destinations, 23 routes (8 active, 0 holddown, 15 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.20.0.0/16 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
[edit]
lab@vMX-1#
Example 2 – Route Filter Using Longer Match
Next, we can change the match from exact to longer.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.20.0.0/16 longer;
}
then accept;
}
term final {
then reject;
}
[edit]
lab@vMX-1#
We should no longer see the 172.20.0.0/16 network itself, only the subnets that belong to that range and have a prefix length longer than /16. Taking the 172.20.0.0/24 route in particular, it matches the longest prefix length match against 172.16.0.0/16, and it also matches the ‘longer’ match type by being a /24 prefix.
[edit]
lab@vMX-1# run show route protocol bgp terse
inet.0: 23 destinations, 23 routes (12 active, 0 holddown, 11 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.20.0.0/22 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.1.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.2.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.3.0/24 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
[edit]
lab@vMX-1#
Example 3 – Route Filter Using Orlonger Match
If we now make the match type orlonger, we should see the 172.16.0.0/16 route and all the subnets within that range.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.20.0.0/16 orlonger;
}
then accept;
}
term final {
then reject;
}
[edit]
lab@vMX-1# run show route protocol bgp terse
inet.0: 23 destinations, 23 routes (13 active, 0 holddown, 10 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.20.0.0/16 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/22 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.1.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.2.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.3.0/24 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
[edit]
lab@vMX-1#
Example 4 – Route Filter Using Prefix Length Match
In this example, we will change the match type to prefix length and set it to /23 to /25. Given the prefix match we have set, we should only see the four /24 routes from 172.20.0.0/16.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.20.0.0/16 prefix-length-range /23-/25;
}
then accept;
}
term final {
then reject;
}
[edit]
lab@vMX-1# run show route protocol bgp terse
inet.0: 23 destinations, 23 routes (11 active, 0 holddown, 12 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.20.0.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.1.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.2.0/24 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.3.0/24 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
[edit]
lab@vMX-1#
Example 5 – Route Filter Using Upto Match
Now we’ll change the match to be upto /23, which means we should match the /16 and /22 routes only.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.20.0.0/16 upto /23;
}
then accept;
}
term final {
then reject;
}
[edit]
lab@vMX-1# run show route protocol bgp terse
inet.0: 23 destinations, 23 routes (9 active, 0 holddown, 14 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.20.0.0/16 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/22 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
[edit]
lab@vMX-1#
Example 6 – Multiple Route Filters In A Single Term
Up until now, we’ve just had the single route filter. Let’s now use two non-overlapping route filters to get routes from both 172.20.0.0/16 and 172.16.0.0/16.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.20.0.0/16 upto /23;
route-filter 172.16.0.0/16 prefix-length-range /25-/27;
}
then accept;
}
term final {
then reject;
}
[edit]
lab@vMX-1# run show route protocol bgp terse
inet.0: 23 destinations, 23 routes (12 active, 0 holddown, 11 hidden)
+ = Active Route, - = Last Active, * = Both
A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.1.128/25 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.1.192/26 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.16.1.224/27 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/16 B 170 100 65002 I
unverified >10.100.1.2
* ? 172.20.0.0/22 B 170 100 65002 I
unverified >10.100.1.2
inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
As you can see from the output above, we can have multiple route filters with differing match types in the same policy term.
Advanced Route Filter Examples
We will use the same routes as we did for the basic examples. In these examples though we will use over-lapping route filters, and add actions to the route filter terms. The ‘final’ term will be removed as well.
We will be focusing on the 172.16.1.0/24 route and how it is affected by the policies. This is what it looks like before we start.
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.1.0/24 *[BGP/170] 00:01:05, localpref 100
AS path: 65002 I, validation-state: unverified
> to 10.100.1.2 via ge-0/0/1.0
Example 7 – Route Filters With Actions
In this example, we have assigned actions to two route filters. What do you think the local preference value for 172.16.1.0/24 will be?
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.16.0.0/16 orlonger {
local-preference 150;
}
route-filter 172.16.1.0/24 exact accept;
}
then {
local-preference 80;
accept;
}
}
[edit]
lab@vMX-1#
Let’s have a look at the route and find out.
[edit]
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.1.0/24 *[BGP/170] 00:04:58, localpref 100
AS path: 65002 I, validation-state: unverified
> to 10.100.1.2 via ge-0/0/1.0
[edit]
lab@vMX-1#
The local-preference is 100. Which makes sense. The longest prefix match to our route is the route-filter of 172.16.1.0/24 and we match the prefix type (exact). The action applied to that filter is ‘accept’ which is a terminating action, so no further policy processing takes place. The 172.16.1.0/24 route doesn’t have its local preference changed, so it remains at the default of 100.
Example 8 – Route Filters With Non-Terminating Actions
Let’s change the route filter to now have a non-terminating action.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.16.0.0/16 orlonger {
local-preference 150;
}
route-filter 172.16.1.0/24 exact {
local-preference 200;
}
}
then {
local-preference 80;
accept;
}
}
[edit]
lab@vMX-1#
What local preference value should the route 172.16.1.0/24 have? Is it 200?
[edit]
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.1.0/24 *[BGP/170] 00:01:53, localpref 80
AS path: 65002 I, validation-state: unverified
> to 10.100.1.2 via ge-0/0/1.0
[edit]
lab@vMX-1#
The local preference is 80. How does that happen? We know from the previous example that the 172.16.1.0/24 exact route filter matches this route, so why is the local preference not 200?
Setting the local preference value is a non-terminating action. This means that the route will continue to be processed by the policy chain. I suspect what is happening here is that the route filter is setting local preference to 200, the route is further processed through the ‘then’ portion of the policy term and it is getting set to 80.
Example 9 – Route Filters With Multiple Longest Prefix Matches
What happens when we have multiple route filters with the same prefix match and different match types?
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.16.1.0/24 orlonger {
local-preference 200;
accept;
}
route-filter 172.16.1.0/24 prefix-length-range /24-/24 {
local-preference 150;
accept;
}
route-filter 172.16.1.0/24 exact reject;
}
then {
local-preference 80;
accept;
}
}
[edit]
lab@vMX-1#
What does the route look like? What type of match wins?
[edit]
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.1.0/24 *[BGP/170] 00:01:08, localpref 200
AS path: 65002 I, validation-state: unverified
> to 10.100.1.2 via ge-0/0/1.0
[edit]
lab@vMX-1#
The route has a local preference of 200. This isn’t because one match type “wins” over another. It is simply a case of which order they appear in the configuration. We can prove this by changing the order of the route filters.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.16.1.0/24 prefix-length-range /24-/24 {
local-preference 150;
accept;
}
route-filter 172.16.1.0/24 orlonger {
local-preference 200;
accept;
}
route-filter 172.16.1.0/24 exact reject;
}
then {
local-preference 80;
accept;
}
}
[edit]
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.1.0/24 *[BGP/170] 00:00:18, localpref 150
AS path: 65002 I, validation-state: unverified
> to 10.100.1.2 via ge-0/0/1.0
[edit]
lab@vMX-1#
Example 10 – More Route Filters With Terminating Actions
Here is another interesting example to show route filter behavior.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
term test {
from {
route-filter 172.16.0.0/16 orlonger;
route-filter 172.16.1.0/24 longer {
local-preference 200;
accept;
}
route-filter 172.16.0.0/23 orlonger reject;
}
then {
local-preference 80;
accept;
}
}
[edit]
lab@vMX-1#
What happens to the 172.16.1.0/24 route in this case?
[edit]
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (22 active, 0 holddown, 1 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.1.0/24 *[BGP/170] 00:14:22, localpref 100
AS path: 65002 I, validation-state: unverified
> to 10.100.1.2 via ge-0/0/1.0
[edit]
lab@vMX-1#
The route is there with the default local preference. Was that what you were expecting?
So what happened? Remembering the way that route filters get matched, the first part is the longest prefix match, which in this case is ‘route-filter 172.16.1.0/24 longer’. Importantly, the match type is longer, which means a prefix length of /25 or more, which doesn’t match the route.
Since the route doesn’t match the policy, it moves on to the next term, or in this case the next policy, since there is only one term. The next policy is the default BGP policy which accepts all BGP routes. Thus, the route 172.16.1.0/24 is accepted without modification.
Route Filter Walkup
After the last example, it is now a good time to talk about route filter walkup. This configuration changes the behavior of how route filters are processed.
With walkup enabled, the route is first compared to the longest prefix match as normal, but if the match type means the route isn’t a match, the route can be compared to the route filter with the next longest prefix match. In this way, the route can “walk up” the route filters until it either matches or must go on to the next term or policy.
Walkup can be enabled at either a global level applying to all policies, or on a policy-by-policy basis. If it is enabled at a global level, it can be disabled on a policy-by-policy basis as well.
It can be set globally with:
set policy-options defaults route-filter walkup
It can be set per policy with:
set policy-options policy-statement <policy-name> defaults route-filter walkup
Example 11 – Route Filters With Walkup Enabled
Let’s enable walkup on our policy now.
[edit]
lab@vMX-1# show policy-options policy-statement route-filter-test
defaults {
route-filter walkup;
}
term test {
from {
route-filter 172.16.0.0/16 orlonger;
route-filter 172.16.1.0/24 longer {
local-preference 200;
accept;
}
route-filter 172.16.0.0/23 orlonger reject;
}
then {
local-preference 80;
accept;
}
}
[edit]
lab@vMX-1#
What happens to our 172.16.1.0/24 route?
[edit]
lab@vMX-1# run show route 172.16.1.0/24 exact
inet.0: 23 destinations, 23 routes (21 active, 0 holddown, 2 hidden)
[edit]
lab@vMX-1#
The route is no longer present. Since it failed the match type for the router filter of 172.16.1.0/24 it walked up to the next longest match, which is ‘ route-filter 172.16.0.0/23 orlonger reject’. It matches the prefix, and then the match type of orlonger. The terminating action of reject is taken.
Closing Thoughts
Hopefully, the examples shown here have helped you better understand route filters and how they work.
In their simplest use cases, they can be very straightforward to use. They can become complicated and the behavior isn’t always what we might initially expect when we combine several of them in one policy term and add actions.
They are heavily used in Junos policy, so it is helpful to know them well.