Skip to content
Thomas Mangin edited this page Jul 26, 2026 · 6 revisions

Pre-Alpha. This page describes behavior that may change.

RFC 7947 route server: forwards every received route to every other peer, with zero-copy wire forwarding when peers share an encoding context. Supports dynamic peers for IXP deployments.

Category

Policy.

Configuration

Bound per peer alongside bgp-adj-rib-in for replay on reconnect.

plugin {
    internal rs         { use bgp-rs }
    internal adj-rib-in { use bgp-adj-rib-in }
}

bgp {
    peer client-a {
        connection { remote { ip 10.0.0.1; } }
        session    { asn { remote 65001; } }
        process rs         { receive [ update ]; send [ update ]; }
        process adj-rib-in { receive [ update state ]; }
    }
}

See route reflection for the full reference.

Dynamic peers

For IXP deployments, the route server supports dynamic peers. Instead of configuring each peer individually, define a peer template and let peers connect dynamically:

bgp {
    peer-group ixp-clients {
        session {
            family { ipv4/unicast { prefix { maximum 100000; } } }
        }
        process rs         { receive [ update ]; send [ update ]; }
        process adj-rib-in { receive [ update state ]; }
    }
}

Dynamic peers inherit configuration from the peer group and are created on first connection. RS-client role and community filtering apply per peer.

Behaviour

The plugin receives every UPDATE from every peer and forwards it to every other peer, with no best-path selection. When two peers share a ContextID (same ADD-PATH mode, same ASN format, same extended message support), the wire bytes go out unchanged. When contexts differ, the reactor walks the cached attributes and re-encodes for the destination.

A peer that reconnects triggers a three-phase replay from bgp-adj-rib-in: snapshot, delta, End-of-RIB.

Community filtering is applied per peer when configured, allowing selective route filtering based on standard, large, or extended communities.

The peer-up cut

Replay and live forwarding are two writers to one session, so a route arriving in the establishment window could go out twice, in scheduling order. Because replay carries announcements only, a replayed announce landing after a live withdrawal resurrected a withdrawn route permanently.

The two rails are partitioned at a cut expressed in the reactor's MessageID, which is the only quantity both plugins observe per route. When a peer comes up, the route server records that peer as a live forward target and captures the current MessageID as its cut, in one critical section, so no forward-target selection can see a peer that is a target without its matching cut. A message at or below the cut belongs to the replay; above it, to the live rail. A session bounce recaptures the cut.

The cut is carried as presence plus value, not as a bare number: zero is the ordinary value, not a sentinel (the route server's counter is zero until it takes delivery of its first UPDATE), so "bounded at zero" and "unbounded" must not share a bit pattern.

Forwarding to a peer that is Established but whose peer-up event has not yet arrived is deliberately not added: under the cut such an UPDATE is by definition at or below that peer's cut, so the replay owns it.

When a forward matches no target, the discard log names each peer and its reason (not-up, below-cut, source) rather than reporting a bare count, because the two causes need opposite fixes.

Two duplicate sources were closed alongside this. The route server claims the bgp-peer-up-replay role in its registration so bgp-adj-rib-in does not also self-replay, and bgp-rib no longer replays a peer's Adj-RIB-Out on a first session: a first session has an empty Adj-RIB-Out by definition (RFC 4271 Section 3.2), so anything recorded there is this session's own send. A re-established session cannot yet make that distinction, because neither the state nor the sent event carries session identity.

Forward source resolution

A forward whose source peer cannot be resolved is refused rather than sent with a zero-valued source. The zero suppressed reflection suppression and ORIGINATOR_ID / CLUSTER_LIST injection, both RFC 4456 Section 8 obligations, so a route reflector was forwarding without the loop prevention that RFC exists to provide. It also yielded ORIGINATOR_ID 0.0.0.0, never a valid BGP Identifier, and skipped RFC 7947 policy. Presence in the peer table is not sufficient: a torn-down-but-present peer has had its router ID cleared.

Interactions

  • bgp-adj-rib-in stores received routes for the reconnect replay.
  • The reactor's forwarding pool carries the bytes between peers.
  • bgp-role filters apply per peer when the RFC 9234 Role plugin is loaded.
  • Community filtering applies per peer when configured.

Source

main/internal/component/bgp/plugins/rs/

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally