BGP Communities and AS-Path Filtering on Cisco IOS-XE - 夜莺博客

BGP Communities and AS-Path Filtering on Cisco IOS-XE

Communities let you tag a route once and act on that tag anywhere in the AS, which is far more maintainable than repeating giant prefix lists on every router. This guide shows the working pattern on Cisco IOS-XE: set communities outbound, enable propagation, match them inbound, and pair the tagging with prefix-list and AS-path filtering so a leaked route cannot ride your policy.

Why Communities Beat Long Prefix Lists

A community is a 32-bit attribute carried with the route in AS:value form (RFC 1997). Tagging "our own backup routes" or "customer aggregate" at the edge means every downstream router matches one value instead of re-listing prefixes. Well-known communities you will use constantly:

  • no-export (65535:65281) - use the route, do not advertise it outside the AS.
  • no-advertise (65535:65282) - use it, advertise to nobody at all.
  • local-AS (65535:65283) - keep it inside a confederation sub-AS.
  • 0:666 style self-defined values - your own conventions for RTBH, prepending and preference.

The maintenance argument is the real one. A policy expressed as "prefer upstream A for this customer's routes" becomes a single community match; expressed as a prefix list it becomes 40 lines that must be kept in sync on every border router, and the one router where someone forgets is the router that black-holes traffic. Communities travel with the route, so the tag is applied once at the source of truth.

Community Types and the Format

Three community encodings exist in IOS-XE, and mixing them up is a routine source of "the peer sees nothing" tickets.

Type Size RFC Syntax
Standard 32-bit 1997 65001:200
Extended 64-bit 4360 rt 65001:200, soo 65001:200
Large 96-bit 8092 65000:1:100

Standard communities are what almost every transit and customer policy uses. Extended communities carry route targets and site-of-origin for VPN and EVPN designs. Large communities exist because the global ASN assignment made 32-bit space cramped — two 16-bit halves no longer fit well when a 32-bit ASN is involved. If you only ever set standard communities, you still need to know that send-community extended and send-community both exist, because a route-target design silently breaks without them.

The Trap: send-community

router bgp 65001
 neighbor 203.0.113.1 remote-as 65002
 neighbor 203.0.113.1 send-community standard
 ! add extended or both when route-target style communities are involved

IOS-XE does not propagate communities to eBGP peers unless you ask it to. Symptom: the route-map sets communities, the local table shows them, and the peer sees nothing. Always confirm with show ip bgp 198.51.100.0/24 on the far side rather than trusting the local output.

Two related defaults are worth remembering. Communities are propagated to iBGP peers by default, which is why an internal hop never exposes the bug — the tag appears to work right up to the AS boundary. And the keyword is per neighbour or per peer-group, so a new neighbour added later inherits nothing unless the peer-group carries it. Put send-community standard in the peer-group template, not on individual neighbours.

Setting Communities with the additive Keyword

ip prefix-list PFX_BACKUP seq 10 permit 198.51.100.0/24
route-map SET_COMMUNITY_OUT permit 10
 match ip address prefix-list PFX_BACKUP
 set community 65001:200 additive
route-map SET_COMMUNITY_OUT permit 20
 ! everything else passes untouched

Without additive, set community replaces every existing community on the prefix - including no-export tags you rely on. Leaving a bare permit clause at the end of the route-map matters too: a route-map without a catch-all term silently drops unmatched routes, which is a classic "why did half my prefixes disappear" outage.

Two more gotchas live in the same three lines. A route-map applied outbound with set community but no additive will happily strip a no-export tag that an upstream handed you, and you will then leak a prefix you were asked not to. And multiple set community statements in the same route-map term do not accumulate unless each one carries additive — the last one wins. Build the term once, list every community in a single set community ... additive line, and re-check the peer's view afterwards.

Matching Communities Inbound

ip community-list standard CUST-TAGGED permit 65002:100
route-map FROM_PEER_IN permit 10
 match community CUST-TAGGED
 set local-preference 200
route-map FROM_PEER_IN permit 20
 set local-preference 100

Community-based local-preference is evaluated before AS-path length, so it is the cleanest way to prefer one upstream for specific destinations instead of moving whole tables.

Matching also works with regex, which is how you catch a family of values instead of enumerating them:

ip community-list expanded CUST-ANY permit "65002:1[0-9]{2}"
ip community-list expanded FROM-TRANSIT permit "65002:.*"

An expanded community list matches the community string rather than the numeric value, so quoting and anchors matter. Keep expanded lists narrow: a pattern like .*:.* matches every community on every route and will quietly apply your policy to the whole table.

Backstop with Prefix and AS-Path Filters

ip prefix-list BOGON seq 10 deny 10.0.0.0/8 le 32
ip prefix-list BOGON seq 20 deny 172.16.0.0/12 le 32
ip prefix-list BOGON seq 30 deny 192.168.0.0/16 le 32
ip prefix-list BOGON seq 40 deny 0.0.0.0/0 ge 25
ip as-path access-list 10 permit ^65002_
ip as-path access-list 20 deny _64500_
ip as-path access-list 20 permit .*

Community policy is preference; filters are safety. Apply inbound prefix and AS-path lists on every external peer, and prefer RPKI origin validation for the hijack case. Damping is deliberately not recommended for modern transit policies - the reasoning is in BGP route flap damping and RFC 580 tuning, and the equivalent policy language on IOS-XR is covered in IOS-XR RPL route policy.

AS-Path Regular Expressions That Actually Matter

AS-path filtering is a small regex language and a handful of patterns cover nearly all production use:

Pattern Meaning
^65002_ Originated by AS 65002, one hop away (the standard customer check)
_65002$ Prefix originated by 65002 at the end of the path
_65002_ 65002 appears anywhere in the path
^$ The empty AS-path: only local routes, i.e. originated here
^65002_.* Path begins with 65002
^([0-9]+)(_\1)+$ A path consisting solely of one AS repeated, i.e. prepended by the origin

The underscore is the crucial character: it matches a space, a brace, a comma, or a string boundary, which is why _65002_ cannot accidentally match AS 650021. Anchors at both ends (^...$) make a policy deterministic; without them the engine matches a substring and produces the surprise rejections that keep people up at night.

Verifying Before You Trust It

The local table is not evidence. These four commands are:

show ip bgp 198.51.100.0/24
show ip bgp community 65001:200
show ip bgp community-list CUST-TAGGED
show ip bgp neighbors 203.0.113.1 advertised-routes

The first shows the communities on a specific prefix as they exist locally; the second and third show which routes match a value or list; the fourth shows the exact attribute set the peer will receive, including whether the community survived the outbound route-map. Get in the habit of checking that last one after any policy change — it is the only place where the send-community trap becomes visible on your side of the session.

If you need to re-run policy without tearing the session down, use clear ip bgp 203.0.113.1 soft in where the peer advertises the route-refresh capability, or keep neighbor 203.0.113.1 soft-reconfiguration inbound configured as a fallback. Soft inbound reconfiguration stores a second, unmodified copy of every route the peer sent, so it costs memory — enable it deliberately, not by default on a full table.

A Complete Outbound Policy, Term by Term

Individual snippets hide the sequencing problem, so here is a full outbound policy and how to read it:

ip prefix-list PFX_CUST seq 5 permit 198.51.100.0/24
ip community-list standard RTBH permit 65001:666

route-map TO_TRANSIT permit 10
 match ip address prefix-list PFX_CUST
 set community 65001:200 additive
 set local-preference 250
route-map TO_TRANSIT permit 20
 match community RTBH
 set community 65001:666 additive
route-map TO_TRANSIT permit 30
 set community no-export additive

Terms are evaluated top to bottom and the first match wins, so order encodes priority. Term 10 catches the customer prefix, tags it with a non-standard community used for upstream preference, and raises its local preference. Term 20 catches anything already carrying the blackhole tag and keeps the tag intact through the outbound rewrite. Term 30 is the catch-all: everything not matched above receives no-export, which prevents accidental transit leakage of internal space. Delete term 30 and the route-map silently drops every unmatched route instead of tagging it — one of those two behaviours is what you want, and you should know which.

Note the asymmetry between match and set. A term with no match clause matches everything, which is how catch-alls are built. A term with a match that fails is skipped and evaluation continues. There is no "else" and no abort — the route simply falls through.

The RTBH Pattern in Practice

The 65001:666 convention above is the standard remotely triggered black hole, and it is the most valuable thing communities do in a production network. The idea: an edge router tags a hostile /32 with the blackhole community, that tag propagates inside the AS, and every border router matches it and points the prefix at a discard route instead of a next hop.

! On the border routers
ip route 192.0.2.1 255.255.255.255 Null0
route-map FROM_UPSTREAM_IN permit 10
 match community RTBH
 set ip next-hop 192.0.2.1
route-map FROM_UPSTREAM_IN permit 20

! On the edge router that triggers the drop
route-map TRIGGER_RTBH permit 10
 match ip address host 203.0.113.77
 set community 65001:666 additive

Two rules keep this safe. The trigger route-map must only ever match a /32 — a blackhole tag accidentally applied to a whole aggregate is an outage you will remember. And no-export must be carried alongside the blackhole community, so the poisoned prefix never leaves your AS and causes collateral damage upstream.

Deployment Order That Avoids an Outage

  1. Create the prefix lists, community lists and route-maps. Nothing is applied yet, so nothing can break.
  2. Attach the inbound filters first — prefix lists, AS-path lists, RPKI. Inbound policy can only make the local table smaller, never leak anything outward.
  3. Attach the outbound policy on one peer, then check show ip bgp neighbors <ip> advertised-routes before touching the next.
  4. Verify on the far side. The peer's view of the attributes is the only proof the policy works end to end.

Never apply outbound policy to every peer at once. If the route-map has a typo — a missing catch-all, a community name that does not exist — the failure is a withdrawal of routes and it takes effect immediately across every session you touched. One peer at a time gives you a working reference to compare against.

Pre-Change Checklist

  • Does every route-map have an explicit catch-all term, and do you know whether it should be a permit-no-match or a deny?
  • Is send-community set on the peer or peer-group for every community type you use?
  • Does every set community that should accumulate carry the additive keyword?
  • Are the prefix and AS-path filters applied as a backstop, independent of the community policy?
  • Have you confirmed the result on the far side rather than in the local table?

原文链接:https://ignaonline.com/bgp-communities-and-route-filtering-on-cisco-ios-xe-a-practical-engineers-guide