On this page
Routing Daemon Backends
Pathvector NG is daemon-agnostic: the backend option selects which routing
daemon's native configuration format is rendered and which control channel is
driven. Everything above the daemon layer — peers, templates, PeeringDB,
IRR, communities, policies, the optimizer — is shared by every backend.
| Backend | Config output | Control channel | Status |
|---|---|---|---|
bird (default) |
BIRD *.conf |
birdc socket |
Full feature set |
cairn |
cairnd.toml + policy.conf + staticd.toml |
cairnctrl socket |
Core feature set (see below) |
frr |
frr.conf |
vtysh |
Core feature set (see below) |
Each backend is exercised against released daemon versions by an automated
matrix (tests/bird-matrix, tests/frr-matrix, tests/cairn-e2e,
tests/e2e) — BIRD v2.0.7–v3.4.0, FRR frr-9.1.3–frr-10.7.1, Cairn
0.1.1. Regenerate the README's compatibility table with make compat.
Set it at the top level of pathvector.yml:
asn: 64512
router-id: 192.0.2.1
backend: cairn
Cairn backend
With backend: cairn, pathvector generate renders:
cairnd.toml— AS, router ID, listen addresses, per-neighbor sessions ([[neighbor]]), local[[network]]origination,[fib],[metrics](native Prometheus endpoint) and[[rpki.cache]]when RPKI is enabled.policy.conf— shared prefix-lists/as-path lists plus onefilterper peer per direction (PV_<PEER>_IN/PV_<PEER>_OUT).staticd.toml— only whenkernel.statics*entries exist.
Peer options map onto Cairn's native neighbor fields where they exist
(password, multihop, ttl-security, rr-client, rs-client,
allow-local-as, add-path-*, next-hop-self, per-family listen
addresses, import limits → max_prefixes). Everything else is expressed in
the generated filters: prefix accept-lists, bogon/blocklist/prefix-length
filters, local-pref and community/as-path/prefix preferences, community
add/remove, prepends, private-AS stripping, announce-*, next-hop rewrites,
RPKI roa_check() and enforce-peer-nexthop (as a bgp_next_hop check).
Command mapping:
| Command | BIRD backend | Cairn backend |
|---|---|---|
generate / check |
bird -p validation |
cairnd --check validation |
diff |
cache vs bird-directory |
cache vs cairn-directory |
status |
birdc show protocols |
cairnctrl status + neighbors |
restart |
birdc restart |
cairnctrl reset <neighbor> |
metrics |
pathvector /metrics from birdc |
cairnd's native [metrics] endpoint |
Deploy is a hot reload: rendered files are copied into cairn-directory
and cairnctrl reload is issued — no daemon restart, no BGP session flap.
Cairn-specific settings
| Option | Default | Description |
|---|---|---|
cairn-directory |
/etc/cairn/ |
Where cairnd.toml, policy.conf, staticd.toml are deployed |
cairnd-binary |
/usr/sbin/cairnd |
Path to cairnd (used by check) |
cairnctrl-binary |
/usr/bin/cairnctrl |
Path to cairnctrl (used by status/restart) |
cairn-socket |
/run/cairn/cairnd.sock |
cairnd management socket |
staticd-binary |
/usr/sbin/staticd |
Path to staticd (used by check) |
Unsupported on Cairn (warned, not silently dropped)
Peer features with no Cairn equivalent are logged as warnings at generate
time: raw BIRD filter snippets (session-global, pre/post-import-filter,
pre-export*), filter-transit-asns, filter-as-set, filter-aspa,
blackhole-* communities, filter-never-via-route-servers, RFC 9234 roles,
BFD (requires holo), confederation, gateway/cost, extended-next-hop, L3VPN,
per-peer source addresses, clear-path, and export/receive limits.
Session-role conflicts Cairn enforces (rr-client on eBGP, rs-client /
allow-local-as on iBGP, multihop + ttl-security together) are resolved
by dropping the invalid option with a warning.
Cairn is early-release software; treat backend: cairn as experimental.
tests/cairn-e2e/ exercises the backend end-to-end against a real cairnd:
IPv4+IPv6 BGP sessions and route propagation with a BIRD peer, plus
check/status/diff/restart and cairnd's native metrics endpoint
(14 assertions). Because Cairn is private-beta with no public package repo,
the suite takes the cairn.deb as a local build input — see its README.
FRR backend
With backend: frr, pathvector generate renders a single integrated
frr.conf in Cisco-style syntax: a router bgp block with per-neighbor
sessions (split into address-family ipv4 unicast / ipv6 unicast),
route-maps for import/export policy, ip prefix-lists, ip as-path access-lists, bgp community-lists and bgp large-community-lists, an
rpki node for RTR caches, plus ip route/ip protocol bgp route-map
statements for kernel export. Validation uses vtysh -C -f and deployment
copies the file into frr-directory and issues vtysh -b to push it to
running daemons.
Peer options map onto FRR neighbor/route-map primitives where they exist
(password, multihop, ttl-security, add-path-*, next-hop-self,
maximum-prefix, per-family limits, communities, prepends, remove-private-as,
default-originate, RPKI match rpki, kernel export route-maps). BIRD-only
constructs are expressed through route-map sequences or reported as warnings
— never silently dropped.
Command mapping:
| Command | BIRD backend | FRR backend |
|---|---|---|
generate / check |
bird -p validation |
vtysh -C -f validation |
diff |
cache vs bird-directory |
cache frr.conf vs frr-directory/frr.conf |
status |
birdc show protocols |
vtysh -c "show bgp summary json" |
restart |
birdc restart |
vtysh -c "clear bgp <neighbor>" |
metrics |
pathvector /metrics from birdc |
pathvector /metrics from vtysh |
Deploy is a config push: frr.conf + pathvector.yml are copied into
frr-directory and vtysh -b distributes them to the running daemons. A
plain file copy always happens; vtysh -b is best-effort (it only warns if
FRR is not running, since the file is still picked up on next start).
pathvector metrics polls vtysh -c "show bgp summary json" on each scrape
and exports the same pathvector_protocol_up, pathvector_protocol_routes
and pathvector_bgp_session_info series as the BIRD exporter, plus
pathvector_frr_up as the daemon health gauge (pathvector_bird_up on BIRD).
Because FRR reports one neighbor row per address family under a single peer
name, the FRR series carry an afi label (ipv4-unicast, ipv6-unicast, …)
to keep dual-stack sessions distinct — BIRD instead encodes the family in the
protocol name, and its table label is the BIRD routing-table name (a
different concept), so the label sets aren't identical across backends.
FRR-specific settings
| Option | Default | Description |
|---|---|---|
frr-directory |
/etc/frr/ |
Where frr.conf and pathvector.yml are deployed |
vtysh-binary |
/usr/bin/vtysh |
Path to vtysh (used by check/status/restart/deploy) |
RPKI module note
FRR builds RPKI as a loadable module (bgpd_rpki), not into bgpd itself.
Pathvector emits the standard rpki/rpki cache tcp config, which bgpd
only accepts when started with -M bgpd_rpki (and the module directory
available). Most packaged FRR builds ship and auto-load this module; a
minimal source build may need the flag. vtysh -C validates the syntax
either way.
Version compatibility
The generated config targets FRR ≥ 10.1. tests/frr-matrix/ builds a
spread of releases from source and smoke-tests them (see its README for the
full results); the currently-tested set is frr-9.1.3 through frr-10.7.1.
Two version-specific caveats:
- RPKI (
rpki cache). Pathvector emitsrpki cache tcp <host> <port>(thetcp/sshkeywords were added in FRR 10.1). FRR ≤ 10.0 usesrpki cache <host> <port>instead and rejects the newer form, so on those versions setrpki-enable: false(RPKI is optional) — everything else is unaffected. - FRR ≤ 8.x predates libyang 2 and Python 3.13-era APIs; it is not covered by the matrix and is not expected to work without a legacy build environment.
Unsupported on FRR (warned, not silently dropped)
Peer/global features with no clean FRR equivalent are logged as warnings at
generate time: raw BIRD filter snippets (session-global, pre/post-import,
pre-export*, pre-import-accept), prefer-older-routes, transit-lock,
confederation, filter-aspa/filter-as-set/filter-transit-asns,
blackhole-* communities, filter-never-via-route-servers, remove-private-as
on iBGP sessions, VRRP/BFD/MRT instances, keepalived-config, global
source4/source6, and authorized-providers (ASPA).