Skip to content

configuration bgp role

Thomas Mangin edited this page Aug 16, 2026 · 5 revisions

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

BGP Role (RFC 9234) prevents route leaks by declaring the business relationship between peers. The Only To Customer (OTC) path attribute is stamped on eligible egress updates, and routes carrying OTC that arrive from a non-customer direction are rejected. Ze's implementation is the bgp-role plugin, and it enforces the RFC 9234 rules as a mandatory filter when the peer has a role configured.

The rules do not wait for the peer to advertise the capability. RFC 9234 Section 4.2 says "The locally configured BGP Role is used for the procedures described in Section 5", and Section 8 names the non-compliant remote as the case the local AS must still stamp for. See What role the procedures use.

A minimal working config

bgp {
    peer upstream {
        connection {
            remote { ip 10.0.0.1; }
            local  { ip 10.0.0.2; }
        }
        session {
            asn { local 65000; remote 65001; }
            family { ipv4/unicast { prefix { maximum 1000000; } } }
        }
        role {
            import customer;
            strict true;
        }
    }
}

role { import customer } declares the local role for this peer: "I am a customer of the peer on the other side". strict true requires the peer to advertise the Role capability too; if it does not, Ze rejects the session with a Role Mismatch NOTIFICATION.

Configuration reference

Path Type Default Description
role/import enum none The local role. One of provider, customer, rs, rs-client, peer.
role/export list none Destination roles that may receive routes. See The export set.
role/strict bool false Reject peers that do not advertise the Role capability.

Role can be set at the group level and overridden per peer, like any other inheritable setting. A role on a dynamic peer group reaches every member of that group.

Ze resolves role configuration by peer ADDRESS. A peer that states no connection/remote/ip, and whose name is not itself an address, has its role configuration dropped with a warning naming the peer. The group placeholder dynamic on a peer is refused the same way. Both used to be stored under a key nothing could look up, so the role was inert and silent.

The five roles

RFC 9234 defines five roles. Each one describes a business relationship from the local side's point of view.

Role Code Meaning
provider 0 This side sells transit to the peer (the peer is a customer).
rs 1 Route server at an IXP (the peer is a route-server-client).
rs-client 2 Client of a route server (the peer is a route server).
customer 3 This side buys transit from the peer (the peer is a provider).
peer 4 Settlement-free peering.

Valid peer pairs

The local and remote roles must form one of the five valid pairs.

Local Remote
provider customer
customer provider
rs rs-client
rs-client rs
peer peer

A mismatch (for example, local customer with remote peer) triggers a Role Mismatch NOTIFICATION, code 2 subcode 11, and the session is rejected.

What role the procedures use

The Section 5 rules act on what the PEER is to Ze, not on what Ze is to the peer. Ze resolves that value in one place, for the source peer on ingress and for the destination peer on egress.

Source of the value When it is used
The Role capability in the peer's OPEN Whenever the peer sent one.
The complement of the local import role When the peer sent no Role capability.

The complement is the pair table read the other way.

Local import The peer IS
customer Provider
provider Customer
rs-client RS
rs RS-Client
peer Peer

The complement feeds the RFC MUST gates only. The export set still reads the capability, because unknown there is an operator-selected target rather than a missing answer.

A peer that reconnects without advertising a role no longer keeps its old learned value. A learned role is cleared at the OPEN, not on session down.

OTC filtering

The OTC attribute (type 35) is the wire-level mechanism that RFC 9234 uses to prevent leaks. The Role plugin applies OTC rules on both the receive and the send path.

Both paths are bounded twice.

Bound Effect
Address family IPv4 and IPv6 unicast only. The family comes from MP_REACH_NLRI, or from MP_UNREACH_NLRI when the UPDATE only withdraws, so a VPN, EVPN, FlowSpec or multicast withdrawal is excluded exactly as its announcement is. RFC 9234 Section 5: OTC "MUST NOT be applied to other address families by default".
Reachable NLRI OTC is added only to an UPDATE that advertises a route. A withdraw-only UPDATE, an MP_UNREACH-only UPDATE and an End-of-RIB marker are forwarded untouched. Adding an attribute to one produces a message RFC 4271 Section 4.3 says must not carry path attributes, which RFC 7606 Section 5.2 lets a conforming peer escalate to a session reset.

Suppression is not bounded by the second rule. A route that already carries OTC is withheld from a Provider, Peer, or RS whether or not this particular UPDATE advertises it.

On receipt

Condition Action
OTC is malformed (length is not 4) Treat-as-withdraw (RFC 7606).
OTC present, peer is customer or rs-client Route leak; mark it ineligible and do not install.
OTC present, peer is peer, OTC value is not that peer's AS Route leak; mark it ineligible.
OTC absent, peer is provider, peer, or rs Add OTC with the remote ASN.

The last rule tags routes that come in from a non-customer direction so downstream rules can tell whether a route has "already been leaked once" on its way to this AS. The leak rules enforce the prevention: a customer sending us a route with OTC means the route was upstreamed somewhere it should not have been.

On send

Four checks run in order. The first one that fires decides.

# Check Action
1 The route carries OTC and the destination is a Provider, Peer, or RS Suppress. No source configuration is consulted.
2 The destination is a Provider, Peer, or RS, and Ze's role toward the SOURCE is customer, peer, or rs-client Suppress. This is the Gao-Rexford check.
3 The source states an export set and the destination's capability role is outside it Suppress. Operator policy, not an RFC gate.
4 The destination is a Customer, Peer, or RS-Client, the UPDATE advertises a route, and OTC is absent Add OTC with Ze's local AS for that session.

Check 2 reads the ingress metadata when the route came through the ingress filter, and falls back to the source peer's own import role when it did not. A stored-route replay carries no ingress metadata, and a missing value used to select the permissive branch.

Check 4 does not depend on the source at all. A route from an iBGP peer, a route reflector client, a locally originated route or an API-injected route reaches a Customer WITH OTC. The RFC conditions that rule on the destination only, and without OTC the customer could leak it upward with nothing for a compliant neighbour to catch.

The export set

role { export [ ... ] } names the destination roles that may receive routes from this peer. It is operator policy on top of the RFC gates, and it applies only when the SOURCE peer states it.

Token Meaning
default The RFC 9234 Section 5 defaults for the local role.
unknown Also send to a peer whose role Ze does not know.
A role name provider, customer, peer, rs, rs-client.
Local import default expands to
provider customer, rs-client
customer provider, rs, peer
rs rs-client
rs-client rs, provider
peer customer, rs-client

An unrecognised token is logged as a warning and kept as written, so it matches no destination.

unknown matches two states: a peer whose OPEN declared no role, and a peer whose OPEN was never recorded. Both suppress identically and are counted apart, so the drop reason says which one to investigate. export-set points at the policy; role-unrecorded points at validate-open.

Metrics

Every drop is counted, and the first drop of each reason raises a warning naming the peer. Later drops are counted only, with per-route detail at debug level.

Metric Reason labels
ze_role_route_rejects_total leak, malformed-otc
ze_role_route_suppressions_total otc-present, source-role, export-set, role-unrecorded

A suppression used to be logged at debug with no counter, so a peer whose role was never negotiated could have its advertisements withheld invisibly.

Dynamic peer groups

A role stated on a dynamic peer group reaches every member. A member has no entry in the configuration document, so Ze resolves its role by address first and by group second: a member that states its own role keeps it.

Three decisions take that route: the Section 5 OTC gates, the Section 4.2 OPEN pair check with its strict mode, and the Role capability Ze advertises to the member.

A learned role survives a configuration reload while the configuration still names the peer, or still names the group the member belongs to. An established session sends no second OPEN, so a dropped learned role could never be written back.

Strict mode

strict true is the right default for new deployments. When set, Ze requires the peer to advertise the Role capability in its OPEN message. If the peer does not advertise it, Ze sends a Role Mismatch NOTIFICATION and rejects the session.

When strict is off (the default), Ze proceeds even if the peer does not advertise Role. OTC filtering is still applied based on the local role, but the peer may not be doing its side of the work. This is useful during deployment while your peers catch up, and dangerous in the long run.

Without role

When role is not configured for a peer, and that peer advertised no Role capability, no OTC rule fires for it. Routes it sends are not checked and routes sent to it are neither suppressed nor stamped. The engine does not invent a default role: you either declare one or you do not.

The source side is different, and deliberately so. A route whose SOURCE has no role configuration still reaches a Customer, Peer or RS-Client destination with OTC, because check 4 above conditions the stamp on the destination alone. That covers an iBGP peer, a route reflector client, a locally originated route and an API-injected route.

Verification

ze cli -c "peer upstream capabilities"

The capabilities block shows whether Role was negotiated, which role each side declared, and which side is strict. A session where Role did not negotiate shows role: no in the output.

ze show warnings            # Look for role-mismatch if the session bounces
ze show errors              # notification-sent / notification-received for Role Mismatch events

The operational report bus surfaces role-related NOTIFICATIONs through ze show errors.

See also

Adapted from main/docs/guide/bgp-role.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally