-
Notifications
You must be signed in to change notification settings - Fork 3
community filters
Pre-Alpha. This page describes behavior that may change.
Ze supports tagging and stripping BGP communities on ingress and egress through the bgp-filter-community plugin. The feature has two parts: named community definitions under bgp { community { } }, and per-direction filter rules under filter { ingress/egress { community { } } } that reference those names. Filter rules can be applied at the BGP global, group, or peer level, and the ze:cumulative extension means values from all levels are accumulated rather than replaced.
Communities are defined once under the bgp { community { } } block and referenced by name in filter rules. Three types are supported:
bgp {
community {
standard customer-routes {
value [ 65000:100 65000:200 ];
}
large ixp-local {
value [ 65000:0:1 65000:0:2 ];
}
extended rt-import {
value [ route-target:65000:1 ];
}
}
}
| List | Key | Value format | Description |
|---|---|---|---|
standard <name> |
name | ASN:value |
RFC 1997 standard communities. |
large <name> |
name | GA:LD1:LD2 |
RFC 8092 large communities. |
extended <name> |
name | type-specific | RFC 4360 extended communities. |
Each named set is a leaf-list of string values. You can define as many named sets as needed.
Standard community values accept either the numeric ASN:value form or a well-known name. All names in the IANA BGP Well-Known Communities registry are recognized, including no-export, no-advertise, no-export-subconfed, nopeer / no-peer, graceful-shutdown (gshut), accept-own, accept-own-nexthop, route-filter-v4 / route-filter-v6 and their translated variants, llgr-stale, no-llgr, standby-pe, and blackhole (RFC 7999). Both kebab-case (no-export) and underscore (no_export) spellings are accepted, and these names round-trip on output.
Filter rules live under filter { ingress { community { } } } and filter { egress { community { } } }. Each direction has two leaf-lists:
| Path | Type | Description |
|---|---|---|
filter/ingress/community/tag |
leaf-list (string) | Named communities to add to routes received from this peer. |
filter/ingress/community/strip |
leaf-list (string) | Named communities to remove from routes received from this peer. |
filter/egress/community/tag |
leaf-list (string) | Named communities to add to routes sent to this peer. |
filter/egress/community/strip |
leaf-list (string) | Named communities to remove from routes sent to this peer. |
The values are the names of community sets defined in bgp { community { } }.
Beside the named tag and strip sets, the ingress direction carries three rules the RFCs define. Each is a leaf in the same filter { ingress { community { } } } container, so the four levels above carry them with no extra configuration path.
| Leaf | Type | Default | Meaning |
|---|---|---|---|
relation-tag |
boolean | false |
Write the RFC 8195 Section 3.2 relation-to-origin large community on each route this peer sends. |
relation-function |
uint32 | 3 |
Function number of that large community. RFC 8195 leaves the number to each AS and gives 3 as its example. |
scrub-own-ga |
boolean | false |
Remove inbound communities whose Global Administrator is the local AS. RFC 7454 Section 11. |
scrub-keep-function |
leaf-list (uint32) | empty | Function numbers a peer is allowed to send with the local AS as the Global Administrator. |
blackhole-propagation |
enum | none |
Add no-export or no-advertise to a route that carries BLACKHOLE. RFC 7999 Section 3.2. |
bgp {
group customers {
filter {
ingress {
community {
scrub-own-ga true;
scrub-keep-function [ 100 200 ];
relation-tag true;
blackhole-propagation no-export;
}
}
}
}
}
The steps run in one fixed order on each received route: the named strip sets, then the scrub, then the blackhole guard, then the named tag sets. The order is load-bearing. The guard adds a well-known community, so a scrub running after it would delete what it just added.
RFC 7454 Section 11 asks an operator to scrub inbound communities carrying their own AS number, and to allow only the ones customers and peers use for signaling. So an empty scrub-keep-function list keeps nothing. It does not mean "keep everything".
The scrub covers standard and large communities. It runs on eBGP sessions only: on an iBGP session an own-AS value is this network's own signal to itself, and deleting it would remove the operator's internal policy. Well-known communities are never reached, so NO_EXPORT, NO_ADVERTISE and BLACKHOLE always survive a scrub. The relation-function number is never kept, whatever the list says, because a kept relation function would let a peer state its own relation to this AS.
The parameter says what the peer IS to this AS: 2 for a customer, 3 for a peer, 4 for a provider. It comes from the role the bgp-role plugin resolved, which prefers a Role capability the peer announced over the local configuration.
Three sessions get no tag: one whose role does not resolve, an iBGP session (its sender is inside the local AS), and a route-server or route-server-client session (RFC 7947 requires transparency there).
The value is a large community <local-AS>:<function>:<parameter>. Any own-AS large community already carrying that function number is removed first, so a peer cannot state its own relation to you.
RFC 7999 Section 3.2 asks a receiver to stop a BLACKHOLE-tagged prefix propagating outside the local AS, and Section 3.1 leaves the choice between NO_EXPORT and NO_ADVERTISE to the operator's routing policy. The guard adds the community. It does not discard traffic: that is blackhole honoring below. RFC 7999 Section 3.1 makes ignoring the community conformant, so none is a supported state.
Ze honors three community values on egress with no configuration, for every peer and every deployment.
| Community | Value | Ze sends the route to |
|---|---|---|
NO_EXPORT |
0xFFFFFF01 | internal peers only |
NO_ADVERTISE |
0xFFFFFF02 | no peer at all |
NO_EXPORT_SUBCONFED |
0xFFFFFF03 | internal peers only |
The rule applies to a route ze RECEIVED from a peer. A route ze originates and tags itself is still advertised, because tagging your own route is how the community is meant to be used.
The check reads the received route, so an egress policy that strips these values does not restore advertisement. FRR and BIRD apply the route-map first, so a strip there does restore advertisement. Ze diverges from both, deliberately: an operator policy cannot grant what an RFC MUST NOT refuses. There is no configuration switch, because a switch here would be a switch to violate the RFC.
Withdrawals are not affected. All three clauses forbid ADVERTISING the route. One UPDATE can carry withdrawn routes and an announcement together, and a peer refused the announcement still receives the withdrawals, so it never keeps a prefix ze can no longer take back.
Each suppression increments ze_bgp_wellknown_community_suppressed_total, labelled by community. Nothing else reports it.
session { community { send ... } } selects which community attribute types leave on a session. The list takes standard, large, extended, all, or none. Unset is all.
bgp {
peer transit-a {
session { community { send [ standard ]; } }
}
}
A type that is not selected is removed from every UPDATE sent to that peer, on both forward rails. Two attributes are the exception and they are refused out loud rather than silently: OTC (RFC 9234 Section 5) and ORIGINATOR_ID (RFC 4456 Section 8) must be preserved unchanged once set, so a suppression of either is logged and not applied.
A peer can ask Ze to discard the traffic for a prefix by tagging the announcement with a community both sides agreed on. Ze installs a discard route for that prefix. There is no next-hop to allocate and no static route to pre-create.
Honoring is off by default and is configured per session, in a blackhole container at the bgp, group, or peer level. Both leaf-lists accumulate across the levels.
| Leaf-list | Meaning |
|---|---|
communities |
The communities this session agreed to honor. blackhole and 65535:666 are the same well-known value; any ASN:VAL works. |
prefixes |
The prefixes this peer is authorized to advertise. A received blackhole is honored only when one of them covers it and is equal or shorter. RFC 7999 Section 3.3. |
bgp {
peer transit-a {
blackhole {
communities [ blackhole 65001:666 ];
prefixes [ 192.0.2.0/24 198.51.100.0/24 ];
}
}
}
Both conditions must hold. prefixes alone turns standard RTBH on, because stating the blocks a neighbor may blackhole within IS the explicit configuration directive RFC 7999 Section 4 asks for, and communities then resolves to the well-known value. communities alone honors nothing: a community with no authorized prefix covers nothing. Neither list means nothing is honored, which is Section 4's default.
A stated list is taken exactly. The well-known value is NOT added to it, so an operator who names 65001:666 alone honors that value and not 65535:666.
prefixes asks a different question from a prefix list. A prefix list bounds the LENGTH of an announcement, so a 192.0.2.0/24 le 24 entry rejects the /32 inside it. This leaf-list asks whether the peer may advertise a prefix that CONTAINS the announcement, so 192.0.2.0/24 covers every host route inside it.
A listen-range group states the agreement for every session it accepts. Such a session has no peer block, so the group is where an IXP route server writes one container for all of its members.
RFC 7999 Section 3.1 requires the two networks to agree on use of the BLACKHOLE community before it is advertised, and naming it on the peer is Ze's half of that agreement.
announce blackhole <prefix> reaches only the sessions whose resolved list holds 65535:666, under either spelling. A peer with no blackhole block, or one that named only its own value, is left OUT of the announcement. It is not sent the prefix untagged: an ordinary announcement of a host route under attack attracts the traffic the operator asked to have discarded. When no selected peer agreed, the command fails and names the peers that did not.
announce unicast <prefix> community 65535:666 meets the same gate, because the obligation is about the community rather than the verb. Any other community value is untouched.
An operator running rpki { action { invalid reject; } } must also set blackhole-exempt on the session, or no blackhole announcement is honored. See RPKI.
The YANG module ze-filter-community augments the BGP configuration at four levels:
// Named community definitions
augment "/bgp:bgp" {
container community {
list standard { key "name"; leaf name { type string; } leaf-list value { type string; } }
list large { key "name"; leaf name { type string; } leaf-list value { type string; } }
list extended { key "name"; leaf name { type string; } leaf-list value { type string; } }
}
}
// Filter config grouping (reused at all levels)
grouping community-filter-fields {
container ingress {
container community {
leaf-list tag { type string; ze:cumulative; }
leaf-list strip { type string; ze:cumulative; }
leaf relation-tag { type boolean; default "false"; }
leaf relation-function { type uint32; default 3; }
leaf scrub-own-ga { type boolean; default "false"; }
leaf-list scrub-keep-function { type uint32; ze:cumulative; }
leaf blackhole-propagation { type enumeration { enum none; enum no-export; enum no-advertise; } default "none"; }
}
}
container egress {
container community {
leaf-list tag { type string; ze:cumulative; }
leaf-list strip { type string; ze:cumulative; }
}
}
}
// Applied at four levels, into the filter container each level already has:
augment "/bgp:bgp/bgp:filter" { uses community-filter-fields; } // global
augment "/bgp:bgp/bgp:group/bgp:filter" { uses community-filter-fields; } // group
augment "/bgp:bgp/bgp:group/bgp:peer/bgp:filter" { uses community-filter-fields; } // peer inside group
augment "/bgp:bgp/bgp:peer/bgp:filter" { uses community-filter-fields; } // standalone peerAll four tag and strip leaf-lists are marked ze:cumulative, and so is scrub-keep-function. This means that values from the BGP global level, the group level, and the peer level are accumulated (appended together) rather than the most-specific level replacing the others.
For example, if the global config tags customer-routes and a group also tags ixp-local, a peer in that group gets both customer-routes and ixp-local tagged on its routes. This is different from standard YANG leaf-list behavior, where the peer-level value would replace the group-level value.
The accumulation order is: bgp (global) + group + peer. All three levels contribute.
The community-filter-fields grouping is augmented at four points in the config hierarchy:
| Level | Config path | Scope |
|---|---|---|
| BGP global | bgp { filter { ... } } |
Default for all peers. |
| Group | bgp { group <name> { filter { ... } } } |
All peers in this group. |
| Group/peer | bgp { group <name> { peer <name> { filter { ... } } } } |
One peer inside a group. |
| Standalone peer | bgp { peer <name> { filter { ... } } } |
One peer outside any group. |
Because of ze:cumulative, rules at broader levels are not overridden -- they stack. A peer inside a group inherits the global tags, the group tags, and its own tags.
A common IXP deployment: tag customer routes with a local community on ingress, and strip internal communities before sending routes to IXP route servers on egress.
bgp {
community {
standard customer-origin {
value [ 65000:100 ];
}
standard internal-ops {
value [ 65000:999 65000:998 ];
}
large ixp-peer-id {
value [ 65000:0:42 ];
}
}
// Global default: strip internal communities on egress
filter {
egress {
community {
strip [ internal-ops ];
}
}
}
group customers {
// Tag all customer routes on ingress
filter {
ingress {
community {
tag [ customer-origin ];
}
}
}
peer customer-a {
connection { remote { ip 10.0.0.1; } local { ip 10.0.0.2; } }
session { asn { local 65000; remote 65001; } }
}
peer customer-b {
connection { remote { ip 10.0.0.3; } local { ip 10.0.0.4; } }
session { asn { local 65000; remote 65002; } }
}
}
group ixp-rs {
// Tag routes sent to route servers with the IXP peer identifier
filter {
egress {
community {
tag [ ixp-peer-id ];
}
}
}
peer rs1 {
connection { remote { ip 10.100.0.1; } local { ip 10.100.0.2; } }
session { asn { local 65000; remote 65500; } }
}
}
}
In this configuration:
- Routes from
customer-aandcustomer-bare tagged withcustomer-origin(65000:100) on ingress (group-level rule). - Routes sent to
rs1are tagged withixp-peer-id(65000:0:42) on egress (group-level rule) and haveinternal-ops(65000:999, 65000:998) stripped on egress (global-level rule). Both rules apply because ofze:cumulative. - Routes sent to any peer have
internal-opsstripped on egress (global-level rule).
- BGP policies for the broader policy framework.
- BGP peers for peer and group configuration.
- Plugin: bgp-filter-community for the plugin internals.
- Plugin: bgp-rs for the route-server control communities and how they are stripped.
- RPKI for the blackhole exemption on a session that rejects Invalid routes.
- Overview for the surrounding config model.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Telemetry
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology