Ze can operate as a route server (RFC 7947) or route reflector, forwarding received routes to other peers. The bgp-rs plugin handles route forwarding with zero-copy wire optimization when peers share the same encoding context.
plugin {
internal rs {
use bgp-rs
}
internal adj-rib-in {
use bgp-adj-rib-in
}
}
bgp {
peer client-a {
remote { ip 10.0.0.1; as 65001; }
local { ip 10.0.0.254; as 65000; }
router-id 10.0.0.254;
family { ipv4/unicast; }
process rs {
receive [ update ]
send [ update ]
}
process adj-rib-in {
receive [ update state ]
}
}
peer client-b {
remote { ip 10.0.0.2; as 65002; }
local { ip 10.0.0.254; as 65000; }
router-id 10.0.0.254;
family { ipv4/unicast; }
process rs {
receive [ update ]
send [ update ]
}
process adj-rib-in {
receive [ update state ]
}
}
}
The route server forwards all received routes to all other peers. There is no best-path selection -- every route from every peer is forwarded to every other peer. This is the RFC 7947 route server model used at Internet Exchange Points.
When two peers negotiate identical capabilities (same ADD-PATH mode, same ASN format, same extended message support), they share the same encoding context. Routes between peers with matching contexts are forwarded as raw wire bytes without re-encoding -- no parse, no rebuild, no allocation.
Each destination peer has a dedicated forwarding worker (long-lived goroutine with a buffered channel). When a destination peer is slower than the update rate:
- The channel buffer absorbs short bursts (default capacity: 64 items)
- If the channel is full, items go into a per-worker overflow buffer
- The worker fires a congestion event (visible in logs and Prometheus metrics)
- When the peer catches up and the channel drains below 25%, congestion clears
Overflow uses a two-tier pool: per-peer pools (64 slots) absorb steady-state traffic, and a shared MixedBufMux overflow pool (auto-sized from peer prefix maximums, overridable via ze.fwd.pool.size byte budget) bounds overflow memory. When the overflow pool is exhausted, items proceed without a pool handle and a warning is logged. Routes are never dropped -- missing a route update is worse than using extra memory. Prometheus metrics expose per-destination overflow depth (ze_bgp_overflow_items), per-source overflow ratio (ze_bgp_overflow_ratio), and global pool utilization (ze_bgp_pool_used_ratio).
When a peer reconnects, the route server replays all stored routes from other peers:
- Full snapshot replay from adj-rib-in
- Delta loop catches routes received during replay
- End-of-RIB sent when caught up
The bgp-rs plugin requires:
receive [ update ]-- receives route updates from the peersend [ update ]-- sends forwarded routes back to the peer
The bgp-adj-rib-in plugin stores received routes for replay on peer reconnect.
Routes in transit can be managed via cache commands:
| Command | Description |
|---|---|
show cache |
List cached messages |
request cache retain <id> |
Prevent cache eviction |
request cache release <id> |
Release a cached message |
request cache expire <id> |
Remove a cached message immediately |
request cache forward <id> <peer> |
Forward a cached message to a peer |
When bgp-rs is not loaded, received routes are not forwarded to other peers. The bgp-rib plugin stores routes and performs best-path selection, but does not re-advertise them. To forward routes between peers, load the bgp-rs plugin.