BGP AS-Path Regex Tester

From vendor documentation

Test a BGP AS-path regular expression against a list of real AS paths, one answer per line. Expands the Cisco underscore metacharacter, explains each token in plain language and ships a preset library.

Pattern

Vendor syntax: _ is the path boundary on Cisco, Arista and Huawei.

Substituted into presets that contain a placeholder.

Preset library

Click to load; each one is justified below

Vendor dialect

_ expands to a boundarydocumented

The underscore matches an AS path delimiter: a space, comma, brace, parenthesis or bracket — or the start/end of the string. Regexes are matched leftmost-longest.

Source: Cisco IOS IP Routing: BGP Command Reference — "Regular Expressions" (as-path access-list)

Expanded expression

What actually gets compiled after vendor expansion

Regex as compiled
(^|[\s{}()\[\],]|$)3356(^|[\s{}()\[\],]|$)

Each _ became (^|[\s{}()\[\],]|$) — an AS-path delimiter or the start/end of the string.

Results

4 of 8 path(s) match

Blank lines and lines starting with #, ! or // are ignored.

AS pathResultMatched text
65001no match—
65001 65002no match—
65001 65002 3356 15169match" 3356 "
3356 15169match"3356 "
64512 65001no match—
65001 65002 3356 15169 2914 174 1299match" 3356 "
3356match"3356"
1 2 3 4 5 6 7no match—

Export

What each token means

So the next pattern does not need this tool

  • •3356 — the literal AS number 3356.
  • •_ — an AS path **boundary**: a space, comma, brace, parenthesis or bracket, or the very start/end of the path. Cisco, Arista and Huawei define it this way; Junos does not.

Preset explanations

  • Originated by this AS
    ^65001$

    The whole AS path is exactly this one ASN, so this AS originated the prefix. Cisco/Arista/Huawei/H3C write this as ^65001$ in an as-path access-list, or ^$ for a locally originated (iBGP-injected) route.

  • Any path transiting this AS
    _65001_

    This ASN appears anywhere in the path with a boundary on both sides: directly connected, two hops away, or ten hops away. The single most common as-path filter.

  • Contains a private 16-bit ASN
    (?<![0-9])(?:6451[2-9]|645[2-8]\d{1}|6459\d{1}|64[6-8]\d{2}|649\d{2}|650\d{2}|65[1-4]\d{2}|6550\d{1}|6551\d{1}|6552\d{1}|6553[0-4])(?![0-9])

    The RFC 6996 private block 64512–65534, as one exact range rather than a guess. The digits are bounded by a digit lookaround, not by \b: AS numbers are word characters, so \b64512\b also matches inside 645121. The RFC 5398 documentation block 64496–64511 and the reserved 65535 are deliberately outside the range.

  • Contains a private 32-bit ASN
    (?<![0-9])(?:420\d{7}|42[1-8]\d{7}|4290\d{6}|429[1-3]\d{6}|42940\d{5}|4294[1-8]\d{5}|429490\d{4}|42949[1-5]\d{4}|4294960\d{3}|429496[1-6]\d{3}|42949670\d{2}|42949671\d{2}|429496720\d{1}|42949672[1-8]\d{1}|429496729[0-4])(?![0-9])

    The RFC 6996 private 32-bit block 4200000000–4294967294, generated and then tested against every value in the range. The final reserved ASN 4294967295 is excluded. Read a match as "this prefix carries a private 32-bit ASN".

  • Paths longer than 5 hops
    ^([0-9]+ ){5,}

    Five or more "ASN followed by a space" at the start of the path means at least six ASNs, i.e. an AS path length of 6 or more, so at least five AS hops. Anchoring at ^ matters: without it the pattern also matches deep inside longer paths, which is usually not what is meant.

  • Locally originated vs received
    ^$

    An empty AS path is what a router shows for a prefix it originated itself — there are no ASes between it and the prefix. Everything else has been received from a neighbour. Written ^$ in a VRP as-path-filter; on IOS the equivalent is matching the empty path in an as-path access-list.

Frequently asked

What does the underscore mean in a Cisco AS-path regex?
It matches an AS path delimiter — a space, comma, brace, parenthesis or bracket, or the start or end of the path. So _65001_ matches 65001 anywhere as a whole ASN, and does not match the 65001 inside 650011.
Why did my _65001_ pattern not match in this tool?
JavaScript treats an unescaped underscore as a literal character, so the tool expands every underscore into (^|[\s{}()\[\],]|$) before compiling and shows you the expanded pattern. If the result still surprises you, check whether the path really contains that ASN as a separate token.
Does this work the same on Juniper?
No, and the tool says so when you pick Junos. Junos writes boundaries as (^| ) and ( |$) or uses .*, and treats a bare underscore as a literal — so the tool deliberately does not rewrite it there rather than pretending the dialects are identical.
How do I find prefixes carrying a private ASN?
Use the "Contains a private 16-bit ASN" preset. It is generated from the exact RFC 6996 range 64512-65534 and tested against every value in it, because hand-written ranges like _6451_ silently over-match.
What is the difference between ^65001$ and _65001_?
^65001$ requires the whole AS path to be exactly 65001, which means that AS originated the prefix. _65001_ matches 65001 anywhere in the path, so it also catches prefixes merely transiting that AS.

Next