How to use AS path matching in your BGP policies

AS path is one of the most fundamental attributes of a (e)BGP advertisments. Its length is the first parameter in the best path selection algorithm (shorter is better), and it's also the sole mechanism of loop detection (if an AS is seen twice, there's a loop). However, despite the important role it plays behind the scenes, it's rather underutilized in routing policies.

A lot of time when prefix-list or specific route-map rule options such as next-hop can do, route filtering and modification based on AS path can do it better.

Let's see how to use it.

The as-path-list construct

Just like you use a prefix-list for prefix-based filtering and a community-list for community value based filtering, AS paths have their own policy building block — as-path-list.

The basic syntax is:

set policy as-path-list Foo rule 10 description "some description"
set policy as-path-list Foo rule 10 action (permit|deny)
set policy as-path-list Foo rule 10 regex "some regex"

The action parameter has the usual pitfall: if you use it in a route-map, "permit" means "match" and "deny" means "don't match".

The most interesting part is the regex. The syntax and semantics of AS path regular expressions is a superset of POSIX 1003.2, extended with the "_" character. If you are new to regular expressions (which are not quite regular in this case — but that's another story), here's a quick reference:

Boundaries
The ^ character matches the start of the string. The $ character matches the end of the string. The expression "^$" thus matches an empty string. They can also be used for matching exact strings rather than substrings, for example, "^123 456$" will match only "123 456" but not "100 123 456 200".
Wildcard
The _ character is an extension of the normal syntax — it matches any AS path separator, most commonly a space, but aggregation adds some more. So "_123_456" would match either "123 456" or "{123,456}". It also matches the beginning and end of the path.
Character ranges and quantifiers
"[0-9]" means "any digit from 0 to 9". You can narrow that range to "[1-9]" or "[3-5]" or anything else. It can be followed by a quantifier. The following quantifiers are available: "*" (zero or more), "+" (one or more), and "?" (zero or one). Thus, "[0-9]+" will mean any AS number, and "1[0-9]+" will mean "any AS number that starts with 1".
Groups and backreferences
This is where "regular expressions" stop being regular. By enclosing an expression in parentheses, such as "([0-9]+)", you create a group. That group can later be matched with a backreference. For example, "([0-9]+)_\1" will match "123 123" or "345 345", but not "123 345".

Now let's consider common use cases.

Finding locally originated routes

It's not uncommon to see something like this:

set policy prefix-list LocalRoutes rule 10 action permit
set policy prefix-list LocalRoutes rule 10 prefix 192.168.10.0/24
set policy prefix-list LocalRoutes rule 20 action permit
set policy prefix-list LocalRoutes rule 20 prefix 192.168.20.0/24

set policy route-map Out rule 10 action permit
set policy route-map Out rule 10 match ip address prefix-list LocalRoutes

set protocols bgp 65535 network 192.168.10.0/24
set protocols bgp 65535 network 192.168.20.0/24

set protocols bgp 65535 neighbor 10.20.30.1 route-map export Out

This approach may have its merits, but if the goal is simply to allow all locally originated routes, there's a simpler way. The key idea is that locally originated routes have empty AS path, which we can match with a trivial regex for an empty string ("^$").

set policy as-path-list LocalRoutes rule 10 action permit
set policy as-path-list LocalRoutes rule 10 regex "^$"

set policy route-map Out rule 10 action permit
set policy route-map Out rule 10 match as-path LocalRoutes

Prioritizing routes from a certain AS

Suppose you are connected to multiple networks, and of all those networks, AS64555 has the best link. You want as much of outgoing traffic as possible to go through AS64555. Assuming you can't or don't want to use a dedicated route map for their sessions, how can you match those routes? Pretty simple: make an expression for a string that starts (^) with 64555 followed by a path separator (_).

set policy as-path-list FavoriteAS rule 10 action permit
set policy as-path-list FavoriteAS rule 10 regex "^64555_"

set policy route-map In rule 10 action permit
set policy route-map In rule 10 match as-path FavoriteAS

Detecting AS path prepends

Some people use AS path prepends to make their routes appear worse than they are, most commonly to avoid asymmetric routing when they don't want to route outgoing traffic through your network. Suppose you don't want to leave best path selection algorithm to its own devices and instead want to explicitly honor their request. Adding a community string for that purpose would be a better solution, but for the sake of argument let's see how we can do it.

All we know is that a prepended path is a path that contains two or more consecutive entries of the same AS, but we don't have any specific numbers to match. This is where backreferences come into play.

set policy as-path-list Prepended rule 10 action permit
set policy as-path-list Prepended rule 10 regex '([0-9]+)_\1_'

set policy route-map Test rule 10 action permit
set policy route-map Test rule 10 match as-path Prepended
set policy route-map Test rule 10 set local-preference 10

Using regular expressions for route viewing

Policy rules is not the only place where you can use regular expressions. You can also use them as filters for "run show ip bgp". Suppose you want to view all routes from AS64793. This is how you can do it:

vyos@vyos# run show ip bgp regexp "^64793_"
BGP table version is 0, local router ID is 10.217.32.254
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.91.16.0/21    10.217.15.10             0             0 64793 i
*> 10.123.124.0/24  10.217.15.10             1     50      0 64793 64793 64793 64793 i