Configuration
This page walks through BGP peer configuration specifically, since it is the most-configured surface. For every other subsystem's config syntax (interfaces, firewall, L2TP, DHCP, and the rest of Ze's 38 plugin groups), see the generated Configuration Reference, built straight from each plugin's own YANG module.
Peer Settings
Peers are keyed by name (peer <name> { }) with IP and AS in nested containers:
| Setting | Description | Validation |
|---|---|---|
remote { ip; } |
Peer IP address | Required (ze:required) |
remote { as; } |
Peer AS number | Required (ze:required) |
local { as; } |
Local AS number | Required (ze:required, inheritable from bgp level) |
local { ip; } |
Local bind address | Suggested (ze:suggest, can be auto) |
router-id |
Per-peer router ID override | Optional (or inherited) |
name |
Peer key (must start with letter) | Required |
hold-time |
Hold timer (0 or 3-65535 seconds) | 1-2 rejected |
remote { connect; } |
Initiate outbound connections (boolean) | Default: true |
local { accept; } |
Accept inbound connections (boolean) | Default: true |
md5-password |
TCP MD5 authentication | Optional |
outgoing-ttl |
TTL for outgoing packets | Optional |
ttl-security |
Minimum TTL for incoming packets | Optional |
group-updates |
Enable/disable UPDATE grouping | Default: enabled |
Required Field Validation
The ze:required and ze:suggest YANG extensions declare which fields must be present in a peer after config inheritance resolution (bgp -> group -> peer merge).
| Extension | Behavior |
|---|---|
ze:required "path" |
Descendant field must have a value in each list entry after inheritance. Validated at ze config validate, editor commit, and daemon startup for any list (generic, not BGP-only). |
ze:suggest |
Field shown in the web creation form with inherited defaults but not mandatory. |
Peer required fields: connection/remote/ip, session/asn/local, session/asn/remote. Suggested: connection/local/ip.
Fields can be satisfied by inheritance: session/asn/local set at bgp level satisfies the requirement for all peers; session/asn/remote set at group level satisfies it for group members.
Prefix Limits (RFC 4486)
Per-peer per-family prefix maximum enforcement. Mandatory for every negotiated family.
| Setting | Scope | Description |
|---|---|---|
prefix { maximum N; } |
Per family | Hard maximum prefix count. Mandatory. |
prefix { warning N; } |
Per family | Warning threshold. Default: 90% of maximum. |
prefix { teardown true/false; } |
Per peer | Tear down on exceed (default: true) or warn-only. |
prefix { idle-timeout N; } |
Per peer | Seconds before auto-reconnect after teardown (0 = no reconnect). |
When a peer exceeds the maximum: NOTIFICATION Cease/MaxPrefixes (subcode 1) is sent and the session is torn down. With teardown false, the session stays up but further NLRIs for the exceeded family are dropped.
Auto-reconnect uses exponential backoff: idle-timeout x 2^(N-1), capped at 1 hour. Backoff resets on stable session.
PeeringDB integration: resolve peeringdb max-prefix <asn> queries PeeringDB for a peer's ASN and updates prefix maximums automatically. A configurable margin (default 10%) is added to PeeringDB values. The PeeringDB URL is configurable under system { peeringdb { url; margin; } } for private mirrors. Staleness warnings appear when prefix data is older than 6 months.
Prometheus metrics: ze_bgp_prefix_count, ze_bgp_prefix_maximum, ze_bgp_prefix_warning, ze_bgp_prefix_warning_exceeded, ze_bgp_prefix_ratio, ze_bgp_prefix_maximum_exceeded_total, ze_bgp_prefix_teardown_total, ze_bgp_prefix_stale.
Cross-Peer Update Groups
Peers with identical outbound encoding contexts (same ContextID, same policy) are automatically grouped. The reactor builds each UPDATE once per group and fans out the wire bytes to all members, eliminating redundant per-peer UPDATE construction. GroupKey combines the peer's sendCtxID (which encodes ASN4, ADD-PATH, Extended Message, Extended Next Hop, iBGP/eBGP, and ASN values) with a policy key (uniform today, extensible for per-peer export policy).
Groups are maintained by the reactor: peers are added on session establishment and removed on session close. When disabled or when all peers have unique contexts, behavior is identical to per-peer building with negligible overhead (one map lookup per peer lifecycle event).
Default enabled. Configurable via ze.bgp.reactor.update-groups (boolean, default true). ExaBGP migrated configs automatically set update-groups false to preserve per-peer UPDATE behavior.
Session Resilience
| Feature | Description |
|---|---|
| TCP_NODELAY | Disables Nagle's algorithm. BGP messages are application-framed; Nagle only adds latency. |
| DSCP CS6 (RFC 4271 S5.1) | Sets IP_TOS/IPV6_TCLASS to 0xC0 so network QoS policies prioritize BGP traffic. |
| Graceful TCP close | Half-close (CloseWrite) before Close sends FIN instead of RST, ensuring remote peers read pending NOTIFICATIONs. |
| Send Hold Timer (RFC 9687) | Detects when local side cannot write to peer. Duration: max(8min, 2x hold-time). Sends NOTIFICATION code 8 on expiry. |
| Hold timer congestion extension | If data was recently read when the hold timer fires, ze is CPU-congested, not the peer. Resets hold timer instead of tearing down. |
| Write deadline | Forward pool batch writes use a 30s TCP write deadline (configurable via ze.fwd.write.deadline) to prevent stuck peers from blocking workers. |
| Bounded overflow pool | Two-tier pool: per-peer pools (64 slots) absorb steady-state traffic, shared MixedBufMux overflow pool (auto-sized from peer prefix maximums, overridable via ze.fwd.pool.size byte budget) bounds overflow memory. |
| Congestion backpressure | Two-threshold enforcement: pool > 80% denies buffers to the worst destination peer (natural TCP backpressure). Pool > 95% with peer > 2x weight share for 5s triggers forced teardown. |
| GR-aware congestion teardown | Forced teardown is GR-aware: GR peers get TCP close (route retention), non-GR peers get Cease/OutOfResources NOTIFICATION. |
| Pool headroom | ze.fwd.pool.headroom adds extra memory beyond auto-sized baseline, trading memory for delayed teardown decisions. |
Prometheus metrics: ze_bgp_pool_used_ratio, ze_bgp_overflow_items{peer}, ze_bgp_overflow_ratio{source}, ze_forward_buffer_denied_total, ze_forward_congestion_teardown_total.
Route Loop Detection
| Check | RFC | Scope | What it detects |
|---|---|---|---|
| AS loop | RFC 4271 Section 9 | All sessions | Local ASN in received AS_PATH (AS_SEQUENCE or AS_SET) |
| ORIGINATOR_ID loop | RFC 4456 Section 8 | iBGP only | ORIGINATOR_ID matches local Router ID |
| CLUSTER_LIST loop | RFC 4456 Section 8 | iBGP only | Local Router ID found in CLUSTER_LIST |
All three checks run after RFC 7606 structural validation but before prefix limit counting. Routes failing any check are silently treated as withdrawn (no NOTIFICATION, session stays up). Cluster ID defaults to Router ID per RFC 4456 Section 7.
Capabilities Configuration
| Capability | Config Key | Values |
|---|---|---|
| 4-byte ASN | asn4 |
true / false |
| Route Refresh | route-refresh |
true / false |
| ADD-PATH | add-path |
Per-family send/receive/both |
| Extended Message | extended-message |
true / false |
| Extended Next Hop | nexthop |
Per-family AFI mapping |
| Graceful Restart | graceful-restart |
restart-time (0-4095s), long-lived-stale-time (0-16777215s) |
| Role | role |
provider / rs / rs-client / customer / peer |
| Role Strict | role-strict |
true / false |
Route Configuration
Static routes configured per-peer with full attribute control:
- Per-family NLRI with add/del/eor operations
- All standard path attributes
- Watchdog-controlled deferred announcement
- MPLS labels (single and multi-label)
- Route Distinguisher for VPN routes
- Prefix-SID and SRv6 attributes
Process Bindings
External processes receive BGP events and send commands:
- JSON event encoding (peer-up, peer-down, route updates)
- Text command protocol (route announce/withdraw)
- Configurable message filtering (receive-update, receive-open, etc.)
- Neighbor change notifications