Route Filters
Route filters let plugins act as route filters on import (ingress) and export
(egress). Filters are configured per peer, group, or globally using named
references in a filter {} config block. Named filter types are defined under
bgp { policy { } }.
Quick Start
bgp {
policy {
loop-detection no-self-as {
allow-own-as 0;
}
}
filter {
import [ no-self-as rpki:validate ];
}
group customers {
filter {
import [ community:scrub ];
export [ aspath:prepend ];
}
}
}
Filter Types
Filter types are YANG lists under bgp/policy, each marked with ze:filter.
Plugins add new filter types via YANG augment. Each list entry is a named
filter instance referenced by name in peer filter { import/export } chains.
Built-in: loop-detection
Facade over the in-process LoopIngress wire-bytes filter. Configures AS loop
detection (RFC 4271 Section 9) and cluster-list loop detection (RFC 4456 Section 8).
| Leaf | Type | Default | Description |
|---|---|---|---|
| allow-own-as | uint8 (0-10) | 0 | Own-AS occurrences to tolerate before rejecting |
| cluster-id | ipv4-address | (router-id) | Override Router ID for CLUSTER_LIST loop check |
External plugin filters
External plugins declare filters at startup using <plugin>:<filter> names.
Example: rpki:validate, community:scrub.
How It Works
- Filter types are defined in
bgp { policy { } }as named instances. - Per-peer
filter { import/export [ names ] }references filter instances. - Default filters (e.g., loop-detection) auto-populate in every peer's import chain.
- On each received UPDATE, the engine runs the import filter chain.
- On each forwarded UPDATE, the engine runs the export chain per destination peer.
- Each filter responds accept, reject, or modify (delta-only).
Deactivating Filters
Default filters can be deactivated per-peer using the inline inactive: prefix:
bgp {
peer special {
filter {
import [ inactive:no-self-as ];
}
}
}
The inactive: prefix is an input shorthand: it is normalized at parse time into
an out-of-band per-member deactivation marker (the stored filter name stays
clean), so on serialize it round-trips to the canonical inactive: import
no-self-as statement form. The deactivated ref stays in the chain but is
skipped at runtime.
In the CLI editor, use deactivate and activate:
deactivate bgp peer special filter import no-self-as
activate bgp peer special filter import no-self-as
Chain Order
Chains are cumulative across config levels:
| Level | Merge rule |
|---|---|
| Default | Auto-populated first (loop-detection) |
| bgp | Base user chain |
| group | Appended to bgp chain |
| peer | Appended to group chain |
Use the insert command in the CLI editor to control position:
insert filter import reject-bogons before no-self-as
insert filter import new-filter last
Filter Responses
| Response | Meaning |
|---|---|
| accept | Pass update through unchanged |
| reject | Drop update, short-circuit chain |
| modify | Change specific attributes (delta-only) |
Failure Handling
Each filter declares its own failure mode at startup:
| Mode | Behavior on IPC error/timeout |
|---|---|
reject |
Fail-closed: drop the update |
accept |
Fail-open: pass the update through |
Writing a Filter Plugin
A filter plugin is a normal ze plugin that includes filters in its stage 1
declare-registration. See Plugin Guide for general plugin
development and docs/architecture/api/process-protocol.md for the wire protocol.