Skip to content
Thomas Mangin edited this page May 24, 2026 · 8 revisions

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

A BGP peer in Ze is a named entry under bgp { peer <name> { } }. The name is a label you choose, not the peer's IP. You can rename it without losing state, you can refer to it from CLI commands by name, and you can group peers that share defaults under a group { } block.

This page covers what you need to bring up a session, the capabilities and address families you negotiate, prefix limits, authentication, and the per-session policy knobs (route reflection, next-hop control, community filtering, AS override). The configuration model is hierarchical, and most values can live at the global, group, or peer level.

A minimal working peer

bgp {
    router-id 192.0.2.1;
    session {
        asn { local 65000; }
    }

    peer upstream {
        connection {
            remote { ip 10.0.0.1; }
            local  { ip auto; }
        }
        session {
            asn { remote 65001; }
            family {
                ipv4/unicast { prefix { maximum 1000000; } }
                ipv6/unicast { prefix { maximum  200000; } }
            }
        }
    }
}

That is a complete peer. The router ID and local AS live at the BGP level and are inherited. The peer's transport settings go under connection (remote IP, local bind address). The peer's protocol settings go under session (remote AS, the address families to negotiate, their prefix maximums). Ze will not start without per-family maximums (RFC 4486), and the migration from ExaBGP fills them in with a conservative default that you should adjust before you point it at a full table.

Required fields

After inheritance has been resolved, every peer must have these set somewhere in its parent chain.

Field Where it can live Notes
connection/remote/ip Peer Peer's IP address.
session/asn/remote Peer Peer's AS.
session/asn/local BGP, group, or peer Your AS.
connection/local/ip Suggested Local bind address. auto lets Ze pick.

If any required field is missing after inheritance, validators reject the commit with a message naming the field.

Peer types

The same peer block works for eBGP, iBGP, route reflector clients, and route server clients. The difference is in the values, not in the syntax. eBGP is session/asn/local and session/asn/remote set to different ASNs. iBGP is the same ASN on both sides. A route reflector client adds session/route-reflector-client true; plus the cluster-id configuration described under Session policy.

A peer can be passive (connection/local/connect false), accept-only (connection/remote/accept true), or both. The defaults initiate outbound and accept inbound, which is what you want for a normal eBGP session.

Capabilities

Capabilities live under session/capability/ at any inheritance level. The most common ones:

session {
    capability {
        asn4;                                # 4-byte ASN, RFC 6793, on by default
        route-refresh;                       # RFC 2918
        extended-message;                    # RFC 8654, 65535-byte messages
        graceful-restart { restart-time 120; }
    }
}
role { import provider; }                    # RFC 9234 BGP Role, at the peer level

asn4 is on by default and you should not turn it off. route-refresh lets you ask the peer to re-send its full table without bouncing the session. graceful-restart is what keeps the RIB across a daemon restart and pairs with the bgp-persist plugin for the disk side. The role container is a peer-level leaf (not inside capability) as role { import <role>; }; values are provider, customer, peer, rs, and rs-client.

Session policy

These knobs live under session { } and shape how Ze builds outbound UPDATEs and how it treats inbound routes. They are cumulative across BGP, group, and peer levels.

Route reflection (RFC 4456)

Mark a peer as a route reflector client to have Ze apply RFC 4456 iBGP reflection rules: routes learned from this peer are forwarded to all other peers (clients and non-clients), ORIGINATOR_ID is set if absent, and CLUSTER_LIST is prepended with the local cluster ID.

peer client-a {
    connection { remote { ip 10.0.0.1; } }
    session {
        asn { remote 65000; }          # iBGP: same AS as local
        route-reflector-client true;
        cluster-id 10.0.0.254;         # optional, defaults to router-id
    }
}

session/cluster-id is kept in sync with the loop-detection filter's cluster-id automatically, so ingress CLUSTER_LIST checks and egress CLUSTER_LIST prepending use the same value even if you only set one.

Next-hop control

Controls the NEXT_HOP attribute on outbound UPDATEs.

session {
    next-hop auto;        # default
    # next-hop self;        # always rewrite to the local address
    # next-hop unchanged;   # never rewrite (route-server / third-party NH)
    # next-hop 192.0.2.1;   # explicit address
}
Value Behaviour
auto RFC 4271 default: rewrite for eBGP peers, preserve for iBGP peers.
self Always rewrite to the local address. Common for iBGP overlays.
unchanged Never rewrite. Used by route servers and third-party next-hop setups.
<ip> Set next-hop to the literal address.

AS override

session/as-override rewrites the peer's own ASN in the outbound AS_PATH with the local ASN, so the route is accepted at the far end even though its AS_PATH contains the receiver's ASN. This is the standard trick for VPN or multi-site setups where the same customer ASN appears at several sites.

session { as-override true; }

AS override respects the peer's ASN4 negotiation, so 2-byte and 4-byte sessions both work.

Local ASN options

session/asn/local-options tunes how a non-default local ASN shows up in AS_PATH. Both options are leaf-list values; use them individually or together.

session {
    asn {
        local 65001;
        local-options [ no-prepend replace-as ];
    }
}
Option Behaviour
no-prepend Do not prepend the real local ASN in front of the advertised local-as.
replace-as Replace the real local ASN entirely with the advertised local-as.

With both set, AS_PATH contains only the advertised local-as and the true ASN is never visible to the peer.

Community filtering

session/community/send controls which community types Ze includes in outbound UPDATEs. Leave it unset to send everything.

session {
    community { send [ standard large ]; }
}
Value Type
standard RFC 1997 communities (type 8).
large RFC 8092 large communities (type 32).
extended RFC 4360 extended communities (type 16).
all Send all types (default).
none Suppress all community attributes.

Use none for peers that must never receive your internal tags.

Default origination

Per-family: inject a synthetic default route towards the peer. Live under session/family/<name>/.

session {
    family {
        ipv4/unicast {
            prefix { maximum 1000000; }
            default-originate true;
            # default-originate-filter <filter-name>;   # optional gate
        }
    }
}

default-originate is a boolean: true originates 0.0.0.0/0 for IPv4 families, ::/0 for IPv6 families. default-originate-filter is the name of a filter the default must pass before it is emitted. If the filter rejects, the default is not sent. Leave the filter leaf empty to originate unconditionally.

Address families

Each family is a child of session/family/ and carries its own prefix limit.

session {
    family {
        ipv4/unicast    { prefix { maximum 1000000; } }
        ipv6/unicast    { prefix { maximum  200000; } }
        ipv4/mpls-vpn   { prefix { maximum     500; } }
        l2vpn/evpn      { prefix { maximum   10000; } }
    }
}

IPv4 and IPv6 unicast and multicast are built into the engine. Every other family (FlowSpec, EVPN, VPN, BGP-LS, MPLS labels, MUP, RTC, MVPN, VPLS) is provided by an nlri plugin and only available if the plugin is loaded. Run ze --plugins to see which families are registered.

Prefix limits

Prefix limits are mandatory and are enforced per family per peer.

Setting Default Behaviour
maximum required Hard cap. Exceeded means the session is torn down with NOTIFICATION Cease / MaxPrefixes (subcode 1).
warning 90 % of maximum Warning threshold. Logged and exported as a metric.
teardown true Tear down on exceed. Set false to warn-only and drop further NLRIs in the family.
idle-timeout 0 Seconds before automatic reconnect after a teardown. 0 means no reconnect.

ze resolve peeringdb max-prefix <ASN> queries PeeringDB for each peer's ASN and updates the maximums automatically with a configurable margin. Review the change with ze config diff and commit it like any other edit.

Authentication and TTL

Transport-level security lives under connection/.

peer upstream {
    connection {
        md5 { password "shared-secret"; }
        ttl { set 255; max 254; }
    }
}

connection/md5/password enables TCP MD5 (RFC 2385). connection/ttl/set and connection/ttl/max together implement RFC 5082 GTSM. TCP-AO is not implemented.

Filter chain

Import and export filter chains live under peer/filter/ and reference filter instances by name. See Route filters for the filter framework.

peer upstream {
    filter {
        import [ rpki:validate community:scrub ];
        export [ aspath:prepend ];
    }
}

Filter chains are cumulative from BGP globals to group to peer.

Timers and send hold time

Timers live under timer/ at any inheritance level.

timer {
    receive-hold-time 90;
    send-hold-time    480;
    keepalive         0;
    connect-retry     120;
}
Leaf Type Default Description
receive-hold-time uint16 90 Hold time proposed in OPEN (RFC 4271). 0 or 365535.
send-hold-time uint16 0 Send-side hold timer (RFC 9687). 0 or 48065535. 0 means auto: max(480, 2 * receive-hold-time).
keepalive uint16 0 Keepalive interval in seconds (RFC 4271 Section 10). 0 means auto: negotiated hold-time / 3. Non-zero overrides the derivation. Validation rejects values >= hold-time. During negotiation, clamped to negotiated-hold/3 if the peer proposes a lower hold-time.
connect-retry uint16 120 Connect retry interval in seconds (RFC 4271 Section 8).

RFC 9687 introduces a send-side hold timer: if Ze cannot write a KEEPALIVE or UPDATE to a peer within send-hold-time seconds, it tears the session down. This protects against a peer that accepts TCP data but never reads from the socket. With the default receive-hold-time of 90, the effective send hold time is 480 seconds.

Behaviour

The behavior { } container holds operational knobs that affect how Ze builds and sends UPDATEs for a peer. It can live at the group or peer level.

behavior {
    group-updates true;
    manual-eor    false;
    auto-flush    true;
}
Leaf Type Default Description
group-updates boolean true Batch NLRI that share the same path attributes into a single UPDATE rather than one UPDATE per prefix.
manual-eor boolean Manual End-of-RIB. When set, Ze does not send EOR automatically after the initial table dump; trigger it from a plugin or the CLI.
auto-flush boolean Auto-flush routes. When set, Ze flushes pending outbound updates to the peer immediately rather than waiting for the reactor loop.

RIB tuning

rib { } controls per-peer Adj-RIB storage and outbound batching.

rib {
    adj {
        in  true;
        out true;
    }
    out {
        group-updates     true;
        auto-commit-delay 0;
        max-batch-size    0;
    }
}
Leaf Type Default Description
adj/in boolean Maintain Adj-RIB-In for this peer. Required for ze show rib routes received.
adj/out boolean Maintain Adj-RIB-Out for this peer. Required for ze show rib routes sent.
out/group-updates boolean true Group outbound updates (same as behavior/group-updates but scoped to the RIB out path).
out/auto-commit-delay uint32 (ms) 0 Delay before auto-committing a batch of outbound updates. 0 means commit immediately.
out/max-batch-size int32 0 Max updates per outbound batch. 0 means unlimited.

Process content block

The process binding connects a peer to a plugin (built-in or external). The content { } sub-container inside process controls the encoding and filtering of events sent to the plugin.

process my-plugin {
    receive [ update state ];
    send    [ update ];
    content {
        encoding json;
        format   raw;
        attribute minimal;
    }
}
Leaf Type Description
encoding string Event encoding format (json, text, …).
format string Event output format (raw, …).
attribute string Attribute filter expression controlling which path attributes are included.

receive lists the event types the plugin wants to consume: update, open, notification, keepalive, refresh, state, sent, negotiated, plus any plugin-registered types. send lists the message types the plugin may inject: update, refresh, enhanced-refresh.

Verification

ze# peer list
NAME       REMOTE          AS       STATE
upstream   10.0.0.1        65001    ESTABLISHED

ze# peer upstream show
peer upstream {
    connection { remote { ip 10.0.0.1; } }
    session { asn { remote 65001; } }
    state established
    uptime 2h13m
    capabilities [ four-octet-asn add-path route-refresh graceful-restart ]
    families [ ipv4/unicast ipv6/unicast ]
    prefixes received 947213 / max 1000000
}

ze# peer upstream capabilities

ze show peer <name> detail is the long version. ze show bgp summary is the table view across all peers, including per-session uptime.

Dynamic peers (route server)

For IXP route server deployments, Ze supports dynamic peers. Instead of configuring each peer individually, define a peer group template and let peers connect dynamically. Dynamic peers inherit configuration from the group and are created on first connection.

See bgp-rs for the route server plugin configuration.

Common problems

  • Validation fails with "required field missing": one of connection/remote/ip, session/asn/remote, or session/asn/local is not set anywhere in the inheritance chain.
  • Ze refuses to start with "prefix maximum required": every negotiated address family must have a prefix { maximum }. Add it under session/family/<afi-safi>/prefix.
  • Session bounces immediately after Established: check peer <name> show for capability mismatches and the log for the peer's NOTIFICATION code.
  • Session never makes it past Active: TCP is not getting through. Check connection/md5/password, the source IP that connection/local/ip resolves to, and any connection/ttl or firewall rules in the path.

See also

Adapted from main/docs/guide/configuration.md, the ze-bgp-conf.yang schema, and main/docs/features/bgp-protocol.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally