A peer can now send several routes for one prefix, told apart by a path identifier, and each is a route of its own in the table. Wire: - The ADD-PATH capability lists several address families. It was read as exactly one, so the OPEN of a router offering it for IPv4 and IPv6 was malformed and the session never came up. - Prefixes in UPDATEs are `Nlri`: a prefix and a path identifier. The identifier is on the wire, in the body and in MP_REACH/MP_UNREACH, for the families the session uses ADD-PATH for in that direction. Sending and receiving are settled separately, so a session has one codec context for each. Negotiation: - `add_path` on a peer in the configuration: off (the default), receive, send or both, offered for every family offered to the peer. - In use for a family and a direction when one side offered to send and the other to receive. Shown on /statusz and in /api/peers. Table: - A route is known by its peer and path identifier together. Identifiers are stored only in rows that have a non-zero one, so routes of peers that send one route each cost nothing more. - Equal routes from one peer are chosen between by the lower identifier. - /api/routes/received gives each route's path_id. Journal: - A second journal in each shard records every change to any route, for followers that want all the routes of a prefix and not only the best: RibTable::reader_of_all_routes and Event::Routes. This is what sending several routes to a peer will read. It costs nothing while nobody follows it. Sending: prefixes go out with a path identifier where that was agreed, but there is still one route for each prefix to send: only originated routes are announced. Tested with the table and journal model tests extended to path identifiers and to followers of all routes, the codec property tests and fuzz targets extended to ADD-PATH sessions, and end to end in both directions and for the case where only one side offers it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
124 lines
4.2 KiB
Protocol Buffer
124 lines
4.2 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
package bgp.server;
|
|
|
|
// Top level BGP Server configuration.
|
|
message BgpConfig {
|
|
// The router ID, written as a dotted-quad IPv4 address (e.g. "192.0.2.1").
|
|
// Required even on IPv6-only routers per RFC 4271.
|
|
string router_id = 1;
|
|
|
|
// The local 4-byte AS number (RFC 6793).
|
|
uint32 local_asn = 2;
|
|
|
|
// Endpoints to accept incoming BGP connections on.
|
|
// Defaults to 0.0.0.0:179 and [::]:179 when empty.
|
|
repeated TcpEndpoint listen_endpoints = 3;
|
|
|
|
// Peers configured on this server.
|
|
repeated Peer peers = 4;
|
|
|
|
// Routes this router originates and announces to every peer.
|
|
repeated OriginatedRoute originate = 5;
|
|
|
|
// Where to serve the HTTP API, status page and metrics. The port is
|
|
// required. Unset disables the HTTP server.
|
|
TcpEndpoint http_endpoint = 6;
|
|
|
|
// Initial delay between attempts to connect to a configured peer, in
|
|
// seconds. Doubles after each failure up to two minutes. Defaults to 5.
|
|
uint32 connect_retry_seconds = 7;
|
|
|
|
// Connection collisions (RFC 4271 §6.8) against a session that is already
|
|
// Established are, by default, resolved by closing the new connection.
|
|
// When true they are resolved like any other collision: the connection
|
|
// initiated by the higher BGP Identifier survives, and a second connection
|
|
// opened by the same side replaces the first. This lets a peer that
|
|
// restarted take over from a session we have not yet noticed is dead,
|
|
// instead of being refused until the hold timer expires.
|
|
bool collision_detect_established_state = 8;
|
|
}
|
|
|
|
// A route originated by this router. It is announced with an AS_PATH of the
|
|
// local AS and, on each session, that session's local address as next hop.
|
|
message OriginatedRoute {
|
|
// The prefix in CIDR notation, e.g. "192.0.2.0/24" or "2001:db8::/32".
|
|
string prefix = 1;
|
|
|
|
// ORIGIN attribute: "IGP" (the default), "EGP" or "INCOMPLETE".
|
|
string origin = 2;
|
|
|
|
// Extra copies of the local AS to prepend to the AS_PATH. At most 16.
|
|
uint32 as_path_prepend = 3;
|
|
|
|
// MULTI_EXIT_DISC. Left out of the announcement when unset.
|
|
optional uint32 med = 4;
|
|
|
|
// Standard communities (RFC 1997): "ASN:VALUE", or a well-known name such
|
|
// as "NO_EXPORT".
|
|
repeated string communities = 5;
|
|
|
|
// Large communities (RFC 8092): "GLOBAL:LOCAL1:LOCAL2".
|
|
repeated string large_communities = 6;
|
|
}
|
|
|
|
// An IP address and port pair.
|
|
message TcpEndpoint {
|
|
// IP address (V4 or V6).
|
|
string address = 1;
|
|
// TCP port. Defaults to 179 for BGP when unset.
|
|
uint32 port = 2;
|
|
}
|
|
|
|
// Configuration of a BGP peer.
|
|
message Peer {
|
|
// Human-readable name for logging and diagnostics.
|
|
string name = 1;
|
|
|
|
// Address and port to connect to for this peer.
|
|
TcpEndpoint endpoint = 2;
|
|
|
|
// The peer's 4-byte AS number (RFC 6793).
|
|
uint32 remote_asn = 3;
|
|
|
|
// Hold time to advertise in the OPEN message, in seconds (RFC 4271 §4.2).
|
|
// Must be 0 or >= 3. Defaults to 90 when unset.
|
|
uint32 hold_time_seconds = 4;
|
|
|
|
// Source IP address for connections we open to this peer. It is also the
|
|
// next hop of the routes we send it. Required when the peer identifies us
|
|
// by address and the host has several, e.g. when both speakers run on the
|
|
// same machine. Must be the same address family as the endpoint. Unset
|
|
// lets the operating system choose.
|
|
string local_address = 5;
|
|
|
|
// The address families to exchange with this peer. Each is offered to the
|
|
// peer in our OPEN, and is in use on the session only if the peer offers
|
|
// it too (RFC 4760). Defaults to all of them when empty. A session with
|
|
// no family in common is refused.
|
|
repeated AddressFamily address_families = 6;
|
|
|
|
// ADD-PATH (RFC 7911): whether to take several routes for one prefix
|
|
// from this peer, to send it several, or both. It is in use, for each
|
|
// direction and address family, only if the peer agrees. Defaults to
|
|
// off: one route for each prefix, as in plain BGP.
|
|
AddPath add_path = 7;
|
|
}
|
|
|
|
// The directions ADD-PATH can be offered for.
|
|
enum AddPath {
|
|
ADD_PATH_OFF = 0;
|
|
// Accept several routes for a prefix from the peer.
|
|
ADD_PATH_RECEIVE = 1;
|
|
// Send the peer several routes for a prefix.
|
|
ADD_PATH_SEND = 2;
|
|
ADD_PATH_BOTH = 3;
|
|
}
|
|
|
|
// An address family routes can be exchanged for.
|
|
enum AddressFamily {
|
|
ADDRESS_FAMILY_UNSPECIFIED = 0;
|
|
IPV4_UNICAST = 1;
|
|
IPV6_UNICAST = 2;
|
|
}
|