-
Notifications
You must be signed in to change notification settings - Fork 2
policies
Pre-Alpha. This page describes behavior that may change.
Ze does not have a built-in filter language in the style of BIRD's filter DSL or FRR's route-map. Policy is a composition of plugins, assembled by referencing named filters in a peer's filter { import/export } block and (for filters that need tuning) defining their instances under bgp { policy { } }. This is a deliberate design choice: plugins can be written in Go or in any external language, and the engine stays out of the policy business.
This page covers what the current policy surface looks like, how the chain is built, and what the shipping plugins provide. The filter API itself, including filter block syntax, default-filter auto-population, and the inactive: / deactivate mechanism, is documented under route filters; this page is for operators picking policy, not authors writing it.
Ze always runs loop detection on ingress. Without any config, you get:
- Local ASN in AS_PATH (AS_SEQUENCE or AS_SET), per RFC 4271 Section 9.
- Local Router ID as
ORIGINATOR_IDon iBGP sessions, per RFC 4456 Section 8. - Local Router ID in
CLUSTER_LISTon iBGP sessions, per RFC 4456 Section 8.
Routes that fail any check are treated as withdrawn. No NOTIFICATION, the session stays up, the route never enters the RIB.
To tune the check (allow-own-as count, custom cluster-id), define a loop-detection filter instance under bgp/policy:
bgp {
policy {
loop-detection no-self-as { allow-own-as 0; }
}
}
The instance name is then auto-populated at the front of every peer's import chain. To suppress loop detection on a specific peer, use inactive:<name> or deactivate in the CLI editor. See route filters for the mechanics.
When the role plugin is loaded and a peer has a role { import <role> } declaration, RFC 9234 role filtering runs on both ingress and egress. On receipt, routes from an invalid role direction are marked as leaks based on the OTC attribute. On send, OTC is stamped with the local ASN for peers whose role is customer, route-server-client, or peer (but not provider or route-server).
Role enforcement lives in the role plugin, not as an entry in the filter chain. See BGP Role for the reference.
bgp-filter-community is a user filter for tagging, stripping, and matching communities (standard, large, extended). A typical use:
bgp {
peer customer {
connection { remote { ip 10.0.0.1; } }
session {
asn { remote 65001; }
family { ipv4/unicast { prefix { maximum 1000000; } } }
}
filter {
import [ community:scrub ];
export [ community:mark-customer ];
}
}
}
The exact named filters (community:scrub, community:mark-customer, and so on) come from the plugin's own config, which you author to match your community policy. The in-tree plugin ships with a small set of examples, and the plugin reference has the full list.
If you only need to stop Ze from sending standard, large, or extended communities to a specific peer, use the session/community/send leaf instead of a filter. That is a session-level knob, not a filter.
Beyond loop detection, several filter and modifier plugins define their instances under bgp { policy { } } and are then referenced by name in a peer's filter chain. Each plugin registers a filter type; you create named instances of that type.
| Plugin | Filter type | Policy block | Decision |
|---|---|---|---|
bgp-filter-modify |
modify |
modify <name> { set/increment/decrement } |
Always modify (set/inc/dec attributes, community add/remove). See route attribute modifier. |
bgp-filter-remove-private-as |
remove-private-as |
remove-private-as <name> { replace-with strip|peer-as } |
Modify (strips RFC 6996 private ASNs from AS_PATH, or replaces them with the peer AS). |
bgp-filter-aspath-length |
as-path-length |
as-path-length <name> { max N; min N } |
Accept or reject based on AS_PATH hop count. |
bgp-filter-community-match |
community-match |
community-match <name> { entry <community> { type standard|large|extended; action accept|reject } } |
Accept or reject on first matching entry; implicit reject if none match. |
A small example combining a match filter with a modifier:
bgp {
policy {
as-path-length too-long { max 50; }
remove-private-as scrub { replace-with strip; }
modify set-pref { set { local-preference 150; } }
}
peer upstream {
filter {
import [ too-long set-pref ];
export [ scrub ];
}
}
}
For community-match, entry order is significant: the first entry whose community is present in the route decides the outcome, and a route matching no entry is rejected (implicit deny). The type leaf selects which attribute is checked (standard, large, or extended) and defaults to standard; the action leaf defaults to accept.
A chain entry can reference a policy instance in three forms:
-
Plain name:
[ scrub ]. Plain names (no colon) are validated against the policy registry at commit time, so a typo is rejected up front. -
Type form:
[ remove-private-as:scrub ]. -
Plugin form:
[ bgp-filter-remove-private-as:scrub ].
show policy test runs a peer's configured filter chain (or a single named filter) against a hex-encoded BGP UPDATE without forwarding the route, touching the RIB, populating cache, or mutating peer state:
show policy test peer upstream import update <HEX>
show policy test peer upstream export update <HEX>
show policy test peer upstream export filter scrub update <HEX>
<HEX> is a full BGP UPDATE message including the 19-byte header (the 0x prefix is optional). The peer selector comes first, then the direction, then optional filter <NAME>, then update <HEX>. Add source-asn4 false to test with an ASN2 encoding context (default ASN4), which makes AS4_PATH (RFC 6793) the active path carrier.
Output is structured JSON with direction, peer, action (accept/reject/modify), trace (per-filter decisions), text-before, text-after, changed-attrs, and wire-changes (wire-level ops such as AS4_PATH suppressed that the flat filter text cannot express).
Two things people reach for on other daemons are not in Ze: prefix list matching with ge/le modifiers, and AS-path regular expression matching. Neither is implemented.
If you need prefix list matching, the workaround is a custom plugin. The plugin receives UPDATE events, keeps its own prefix table, and calls UpdateRoute with a rewritten attribute set when the prefix matches. This is more code than a filter expression, but it works with what the engine provides.
If you need AS-path regex matching, the same workaround applies.
Every filter chain has the same shape:
- Default filters (auto-populated from
loop-detectionentries underbgp/policy). - User filters from the
bgp { filter { } }block. - User filters from the
group { filter { } }block. - User filters from the
peer { filter { } }block.
The chains are cumulative. A peer inherits the BGP-level chain plus its group's chain plus its own. Each filter in the chain sees the previous filter's output, and each one can accept, reject, or modify. A reject short-circuits the chain.
To insert a filter at a specific position in the chain rather than appending, use insert in the CLI editor:
insert filter import reject-bogons before rpki:validate
A filter that modifies an attribute writes into a ModAccumulator, which is lazy: if no modification happens, no copy of the wire bytes is allocated. This is the engine's copy-on-need story, described in architecture.
Ingress filters run on routes as they come in from a peer. They can mark metadata on the cached entry (which shows up in best-path selection and in later filters) and they can reject routes before they enter the RIB.
Egress filters run per destination peer, per route, as the route is being forwarded. They are the right place to modify per-peer attributes (prepending AS path for a specific peer, adding a customer community, rewriting next-hop).
Because the destination peer is different on every egress, the same underlying cached UPDATE can produce different wire bytes on the way out to different peers. Ze only materialises those different bytes when a filter actually changes something. A destination peer with no egress-modifying filters gets the cached bytes unchanged when source and destination share an encoding context.
The honest picture of what the shipping policy surface covers.
What works well today. Loop detection (loop-detection filter type), RFC 9234 role enforcement (role plugin), RPKI origin validation (bgp-rpki), community tagging and stripping (bgp-filter-community), route attribute modification including set/increment/decrement and community add/remove (bgp-filter-modify, see route attribute modifier), private-AS removal (bgp-filter-remove-private-as), AS-path length filtering (bgp-filter-aspath-length), community matching (bgp-filter-community-match), show policy test dry-run, session-level next-hop control / AS override / community-send control / default-originate (under session), iBGP route reflection (route-reflector-client and cluster-id), and custom policy through external plugins.
What does not. Prefix list matching with ge/le, AS-path regex, a named-policy DSL. If any of these are load-bearing for your deployment, Ze is the wrong answer today.
- Route filters for the filter chain configuration syntax.
- Peers — Session policy for session-level route reflection, next-hop, AS override, community filtering.
- BGP Role for RFC 9234.
- RPKI for origin validation.
- Architecture for the egress copy-on-need story.
Adapted from main/docs/guide/plugins.md and main/docs/guide/redistribution.md.
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
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- 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