VyOSXXXIII · Route PolicyCommunity-list
Community-list — standard, expanded, and regular-expression matching
What you'll learn
- Configure a community-list in standard and expanded forms on VyOS 1.5 LTS
- Distinguish exact-match (standard) from regex (expanded) community matching
- Write community regular expressions that match the intended community set
- Diagnose a community-list that returns no-match for a community that should match
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
The BGP community-list is the policy primitive that filters routes by their communities. Communities are 32-bit tags attached to a BGP route by the originator or by intermediate ASes; the recipient uses them to make policy decisions without inspecting the prefix or the AS-path.
On VyOS 1.5 LTS the community-list comes in two forms: standard (exact-match) and expanded (regular expression). The form the operator chooses determines the matching engine; the operator who confuses the two forms writes a list that matches nothing or matches too much.
This lesson covers the configuration, the matching engine semantics, and the production failure modes.
Standard vs expanded — the two matching engines
A community-list has a type that selects the matching
engine:
- standard (
set policy community-list <name> rule <seq> action permit community <AA:NN>) — matches the exact community valueAA:NN.64512:100matches only64512:100; it does not match64512:10or64512:1000. - expanded (
set policy community-list <name> rule <seq> action permit regex <pattern>) — matches a POSIX regular expression against the string form of the community.^64512:100$matches only64512:100;^64512:[0-9]+$matches every community in AS 64512.
flowchart TB
R["Route with communities\n64512:100 64512:200 64513:50"]
L1{"List type?"}
STD["Standard matching:\neach rule's community\nmatched exactly\nagainst route's\ncommunities"]
EXP["Expanded matching:\neach rule's regex\nmatched against\neach community string"]
P["Permit: at least one\ncommunity matched"]
X["Deny: no community\nmatched any rule"]
R --> L1
L1 -->|standard| STD
L1 -->|expanded| EXP
STD -->|"at least one community\nmatches a permit rule"| P
STD -->|"no community matches\nany permit rule"| X
EXP -->|"at least one community\nmatches a permit regex"| P
EXP -->|"no community matches\nany permit regex"| X
The two engines differ in one key property: a community-list returns permit if any community on the route matches a permit rule. It is not “the route’s community-set must match the list”. It is “the list looks at each community on the route and asks ‘does any of them match?’”.
The operator who forgets this writes a community-list that permits routes they thought were denied, because the route carries multiple communities and one of them happens to match.
The configuration
Standard form
# Exact-match for 64512:100
set policy community-list FROM-PEER-A rule 10 action permit
set policy community-list FROM-PEER-A rule 10 community 64512:100
# Exact-match for 64512:200
set policy community-list FROM-PEER-A rule 20 action permit
set policy community-list FROM-PEER-A rule 20 community 64512:200
# Catch-all deny
set policy community-list FROM-PEER-A rule 1000 action deny
The list evaluates top-to-bottom. The first rule that matches
any community on the route decides. A route with
communities 64512:100 64512:200 is permitted (either rule
10 or rule 20 will fire). A route with community
64513:50 falls through to rule 1000 (deny).
Expanded form
# Regex: any community in AS 64512
set policy community-list FROM-ANY-64512 rule 10 action permit
set policy community-list FROM-ANY-64512 rule 10 regex '^64512:'
# Regex: exact match for 64512:100 only (equivalent to standard)
set policy community-list EXACT-100 rule 10 action permit
set policy community-list EXACT-100 rule 10 regex '^64512:100$'
# Catch-all deny
set policy community-list FROM-ANY-64512 rule 1000 action deny
The expanded form uses POSIX extended regular expressions.
The anchor characters ^ (start of string) and $ (end of
string) are essential for exact-match. Without them,
64512:100 matches 64512:1000, 64512:1005, and every
other community in 64512:1xx, 64512:10xx, etc.
flowchart LR
PAT["Regex pattern"]
A1["^64512: (anchored start)\nmatches: 64512:100 64512:200 64512:1 64512:99999"]
A2["64512: (no anchor)\nmatches: 164512: 64512:100 64512:1000 64512:99999\nalso matches: '164512:5' (contains '64512:')"]
A3["^64512:100$ (anchored both)\nmatches: 64512:100 ONLY"]
A4["^64512:100 (anchored start only)\nmatches: 64512:100 64512:1000 64512:1005 64512:10000"]
PAT --> A1
PAT --> A2
PAT --> A3
PAT --> A4
The unanchored 64512: matches 164512:5 (the substring
64512: appears in 164512:5). The operator who writes an
unanchored regex and expects exact-match is surprised when
the list permits unintended communities.
Sequence semantics
Community-lists are ordered and sequential, like prefix-lists. Two rules in the same list cannot both fire; the first match by sequence wins. The implicit deny at the end of the list applies for any community-set that matches no permit rule.
The operator can mix standard and expanded rules in the same
list; each rule’s action permit community or action permit regex selects the matching engine for that rule. The list
type is per-rule, not per-list.
Operational commands
# The configured list
show policy community-list FROM-PEER-A
# The matching engine's view (FRR)
vtysh -c 'show bgp community-list'
vtysh -c 'show bgp community-list FROM-PEER-A'
# Routes carrying a specific community
vtysh -c 'show ip bgp community 64512:100'
vtysh -c 'show ip bgp community 64512:100 exact-match'
# Routes whose community matches a regex
vtysh -c 'show ip bgp regexp "_64512:.*"'
# Clear the hit counts
clear bgp community-list
The show ip bgp community <value> returns all routes in
the BGP table whose community-set contains <value>. The
exact-match keyword restricts to routes whose only
community is <value>. The show ip bgp regexp returns
routes whose community-set matches the regex (FRR uses an
internal regex that looks similar to expanded community
regex but is distinct).
Failure modes
Standard list with too many communities
The operator writes a standard list with 50 permit rules, one per customer community. The configuration is correct but unmaintainable. A customer adds a 51st community; the operator forgets to update the list. The route is denied by the implicit catch-all.
Diagnostic:
show ip bgp communityreturns empty for the new community.show policy community-listshows the old list.vtysh -c 'show bgp community-list <name>'shows no hit count for the new community.
Fix: replace the 50 permit rules with a single expanded
regex. ^64512:(100|200|...|500)$ matches all 50.
Expanded regex without anchors
The operator writes set policy community-list FOO rule 10 action permit regex '64512:100' (no ^ and no $). The
intent was exact-match. The actual matching is: any community
string that contains 64512:100 as a substring. 64512:1000
matches. 164512:1005 matches. 64512:100 matches. The list
permits too much.
Diagnostic:
vtysh -c 'show bgp community-list FOO'returns hit counts for communities the operator did not intend to match.show ip bgp community 64512:1000returns routes that should have been denied.
Fix: anchor the regex. ^64512:100$.
Community-list with the wrong type
The operator writes set policy community-list FOO rule 10 action permit community 64512:100 intending an exact-match.
The rule is a standard rule. The matching engine compares
the community value 64512:100 exactly. A route with
community 64512:1000 does not match. A route with
community 64512:100 64512:200 is permitted (the
64512:100 community matches).
If the operator wanted the regex semantics, they should have
used set policy community-list FOO rule 10 action permit regex '^64512:100$'. If they wanted exact-match for multiple
communities, the standard form is correct; they need multiple
rules.
Diagnostic:
- The list returns permit for routes that should be denied.
show policy community-listshows the rule as a standard rule (noregexkeyword in the output).
Fix: switch the rule to expanded if regex semantics are needed; otherwise add more standard rules for each community.
Rollback
A community-list change is reversible through the standard VyOS mechanisms:
rollback Nandcommitto revert to a previous configuration revision.delete policy community-list <name>andcommitto remove the list. The referencing route-map is left dangling; the commit validator catches this.delete policy community-list <name> rule <seq>andcommitto remove a single rule.set policy community-list <name> rule <seq> action permit community <AA:NN>(override the deny) to permit everything during a debugging window — restore after.
The VyOS commit validator rejects a route-map that references a missing community-list.
Production discipline
Cross-course references
XXVI-VyOS-BGPAttributes(lessonvyos-xxvi-05-community) covers the BGP community attribute at depth: the four well-known communities, the format, and the path of a community through a route.XXIX-VyOS-BGPCommunitiescovers community-based outbound policy: how to stamp a community and let downstream peers use it.XXXIII-VyOS-RoutePolicy(next lesson,route-map) shows how a community-list is matched against a route in the route-map’smatchclause.
Quiz
Knowledge check · 4 questions
Q1. A standard community-list has rule 10 permitting community 64512:100 and rule 20 permitting community 64512:200. A route arrives with communities 64512:100 64513:50. What is the disposition?
Q2. An expanded community-list with rule 10 regex '64512:100' matches only community 64512:100.
Q3. An operator wants to filter inbound routes from a peer to those carrying the customer's specific community 64512:500. They write `set policy community-list FROM-CUSTOMER rule 10 action permit community 64512:500`. A route arrives with communities 64512:500 64512:600. What happens and what is the fix?
The list is a standard community-list with rule 10 permitting 64512:500. The route carries two communities: 64512:500 and 64512:600. The intent was to filter to only the customer community.
Q4. An operator writes an expanded community-list `set policy community-list FOO rule 10 action permit regex '^64512:'` and applies it via route-map to inbound from a peer. The peer sends 100 routes, all with community 64512:100. The operator expects 100 routes permitted. After the commit, 100 routes are denied. What is wrong?
The regex is `^64512:` (anchored start). The peer sends 100 routes with community 64512:100. The list is referenced from a route-map on the inbound side. The operator expected permit; observed deny.
Passing score: 75%. Answers are checked in this browser.