-
Notifications
You must be signed in to change notification settings - Fork 2
redistribution
Pre-Alpha. This page describes behavior that may change.
Route filters let plugins act on BGP UPDATEs as they move through the daemon. Filters attach on import (ingress) and export (egress), per peer, per group, or globally. You reference them by name in a filter { import/export } block, and you define the tunable instances themselves under bgp { policy { } }. The engine runs the chain on every received or forwarded UPDATE.
Renamed from "redistribution". This page used to describe a
redistribution { import/export }block. Both the block name and the default-filter naming changed. See Migrating from redistribution at the bottom.
The plugin-author side is documented on the plugin development pages. This page is for operators picking filters, not authors writing them.
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 ];
}
peer customer-a {
connection { remote { ip 10.0.0.1; } }
session { asn { remote 65001; } }
filter {
export [ community:mark-customer-a ];
}
}
}
}
Two things happen in this config:
- The
bgp/policyblock defines filter instances. Here,loop-detection no-self-asis an instance of the built-inloop-detectionfilter type with a tuning leaf. External plugin filters likerpki:validateorcommunity:scrubdo not need apolicyentry, because the plugin itself declares them at startup. - The
filter { import/export }blocks reference filter instances by name, and the chains are cumulative from global to group to peer.
The effective import chain for customer-a is no-self-as -> rpki:validate -> community:scrub. The effective export chain is aspath:prepend -> community:mark-customer-a.
This is the biggest conceptual change from the old redistribution model.
- A filter type is a YANG list under
bgp/policymarked with theze:filterextension. Built-in types ship with Ze. External plugins add new types via YANGaugment. The type defines the configurable leaves. - A filter instance is a named entry in that list. You pick the name. You tune the leaves. Each instance is then referenceable by that name in any
filter { import/export }chain.
You can create multiple instances of the same type with different tunings. For example, one loop-detection strict { allow-own-as 0; } for transit peers and another loop-detection relaxed { allow-own-as 3; } for an AS-confederation member, and reference each from the peers that need it.
External plugin filters use the <plugin>:<filter> naming (rpki:validate, community:scrub). Those come from the plugin's stage-1 declare-registration call, not from a policy block.
Configures the BGP loop-detection that runs on every received UPDATE. Loop detection itself is always on, with sensible defaults (reject on the first AS match, cluster ID equal to Router ID). You only need a loop-detection entry if you want to tune those defaults or make the check visible in the filter chain.
| Leaf | Type | Default | Purpose |
|---|---|---|---|
allow-own-as |
0 – 10 | 0 | How many times the local ASN may already appear in AS_PATH before the route is rejected. 0 is RFC 4271 Section 9 behaviour. |
cluster-id |
IPv4 address | Router ID | Override the cluster ID used for CLUSTER_LIST loop detection (RFC 4456 Section 8). If session/cluster-id is set on the peer, the two are kept in sync automatically. |
Checks performed on every received UPDATE:
- AS loop — local ASN in AS_PATH (all sessions, RFC 4271 Section 9).
-
Originator-ID loop —
ORIGINATOR_ID == local Router ID(iBGP only, RFC 4456 Section 8). -
Cluster-list loop — local Router ID (or
cluster-id) in CLUSTER_LIST (iBGP only, RFC 4456 Section 8).
When any check fires, the UPDATE is rejected. The AS-loop threshold is tunable via allow-own-as.
External plugin filters are declared by the plugin at stage 1 of startup with a direction (import, export, or both), a list of attributes they want to receive, and a failure mode. Operators only see the references in config. The declarations live in the plugin.
You reference them as <plugin>:<filter>, for example:
filter { import [ rpki:validate community:scrub ]; }
Some filters are auto-populated into every peer's import chain without being named. Today the only defaults come from loop-detection entries: if you define loop-detection no-self-as { ... } in bgp/policy, that name is prepended to every peer's import chain unless already referenced (explicitly or as inactive:). If you do not define any loop-detection entry at all, no default name shows up in the chain, but loop detection itself still runs with built-in defaults.
Default names always run before any user filter in the chain.
Sometimes you need to turn a default filter off on one peer, for example to accept your own ASN on a specific session. There are two equivalent ways.
In the config, prefix the filter name with inactive: in the import list:
bgp {
peer special {
filter {
import [ inactive:no-self-as ];
}
}
}
In the CLI editor, use deactivate / activate on the individual list entry:
deactivate bgp peer special filter import no-self-as
activate bgp peer special filter import no-self-as
Both forms leave every other peer's chain untouched. For loop-detection specifically, deactivation also suppresses the in-process loop check for that peer — not just the filter-chain reference.
Chains are cumulative across config levels:
| Level | Merge rule |
|---|---|
| Default filters | Auto-populated first (e.g. loop-detection entries). |
bgp { filter } |
Base user chain. |
group { filter } |
Appended to the BGP chain. |
peer { filter } |
Appended to the group chain. |
If the BGP globals declare [ rpki:validate ], the group declares [ community:scrub ], and the peer declares [ aspath:prepend ], the effective import chain for that peer is:
no-self-as -> rpki:validate -> community:scrub -> aspath:prepend
To insert a filter at a specific position rather than appending, use insert in the CLI editor:
insert filter import reject-bogons before rpki:validate
insert filter import new-filter last
insert accepts first, last, before <name>, and after <name> positions.
Every filter call returns one of three responses.
| Response | Meaning |
|---|---|
accept |
Pass the UPDATE through unchanged. |
reject |
Drop the UPDATE. The chain short-circuits: no subsequent filter runs. |
modify |
Change specific attributes (delta only). |
On modify, the filter returns only the changed fields. The engine uses wire-level dirty tracking to re-encode only the touched attributes into the wire bytes. When a filter returns accept with no changes, nothing is re-encoded.
Each filter plugin declares its failure mode at stage 1. Failure means an IPC timeout or an explicit error from the plugin.
| Mode | Behaviour on failure |
|---|---|
reject |
Fail-closed. The UPDATE is dropped. |
accept |
Fail-open. The UPDATE passes through. |
The plugin author picks based on the filter's security semantics. An RPKI validator that fails closed rejects everything when the cache becomes unreachable. An RPKI validator that fails open accepts unvalidated routes. Neither is universally right. The decision lives with the plugin.
This is where the filter framework interacts with Ze's zero-copy architecture. On the egress side, a filter writes attribute modifications into a ModAccumulator that is lazy: if nothing writes to it, no copy of the wire bytes is allocated. A destination peer with no egress-modifying filters receives the cached bytes unchanged when the source and destination share an encoding context.
This is why a route server with identical peers stays fast even with filters declared: the filters run, but they do not allocate when they do not modify.
If you previously wrote:
bgp {
redistribution {
import [ rpki:validate ]
}
}
the new equivalent is:
bgp {
filter {
import [ rpki:validate ]
}
}
External plugin filter references (<plugin>:<filter> like rpki:validate or community:scrub) carry over unchanged. What changes is:
-
Block name.
redistribution { ... }becomesfilter { ... }. -
Loop-detection naming. The old hardcoded default filter names (
rfc:no-self-as,rfc:bogon-check) are gone. Loop detection is now surfaced as theloop-detectionfilter type underbgp/policy; you get the same behaviour by default without writing any config, and you tune it by adding aloop-detection <name> { ... }entry. -
Mandatory / default / user categories collapsed. There are now only default filters (auto-populated from
loop-detectionentries) and user filters (explicit infilter { import/export }).
Writing a filter plugin is the same as writing any Ze plugin, except that the plugin's stage-1 declare-registration includes a filters field listing the filters it provides. See plugin development for the general plugin surface and the in-tree architecture reference for the wire protocol.
- Policies for the operator-facing view of what filters ship today.
- BGP Role for RFC 9234 role enforcement.
-
RPKI for the
bgp-rpkiplugin's validation chain. - Plugin development for writing your own filters.
- In-tree filter guide for the authoritative reference.
Adapted from 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