The routing table's shards started empty and grew as routes came in, each growth moving every row of the shard into a table twice the size. In a profile of the daemon taking in a full table, the growth showed as up to a seventh of the session's time, and the daemon's resident memory had the old and the new table of each shard side by side for a moment. This change adds `RibTable::expect_prefixes`, which reserves room for that many prefixes spread over the shards, and has the server call it at startup with the largest `expected_routes` among the configured peers: the prefixes of several full tables are mostly the same ones. Without `expected_routes` nothing changes. The `full_table` benchmark does the same unless `BENCH_PRESIZE=0`. Measured, the saving in time is within the run-to-run noise: in the Linux VM one peer's table is in the routing table in 0.81 s instead of 0.89 s, and the kernel is in step at about the same time as before; three pairs of runs of the benchmark on a Mac average 0.33 s against 0.35 s. The profile's attribution to the growth was mostly sampling skid. The memory saving is real: 442 MiB resident with one peer's table in instead of 483 MiB, and 626 MiB instead of 632 MiB with four. Also: the profiling script printed nothing for the kernel's change counts because it asked `/metrics` for them; the endpoint is `/metricz`. With that fixed, a four-peer load shows 1.25 million installs for 1.23 million prefixes: the journal already gives the kernel task only the latest change of a prefix when it lags, so no further coalescing of installs is called for. Documentation: `expected_routes` in the configuration reference, the neighbor guide and the proto comment say that the table is sized by it; the testing guide's VM results are brought up to date. Testing: a table test checks that the room is there and is kept; the workspace tests pass. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
638 lines
28 KiB
Protocol Buffer
638 lines
28 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;
|
|
|
|
// Connections are accepted only from the addresses of configured peers;
|
|
// from anywhere else they are closed before a byte is read. When true,
|
|
// any host that can reach a listening endpoint may open a session, as
|
|
// any AS it cares to name, and have its routes taken. That is for
|
|
// testing on a closed network and nothing else.
|
|
bool accept_unconfigured_peers = 9;
|
|
|
|
// Route origin validation (RFC 6811) and AS path verification with the
|
|
// RPKI. Left out, routes are not validated.
|
|
Rpki rpki = 10;
|
|
|
|
// Put the best route of every prefix in the kernel's routing table, so
|
|
// that the machine forwards packets by them. Left out, the daemon only
|
|
// speaks BGP and the machine's forwarding is not touched.
|
|
Kernel kernel = 11;
|
|
|
|
// What is announced, and how, to every peer that has no `export` of its
|
|
// own.
|
|
ExportPolicy export = 12;
|
|
|
|
// Let routes say, with communities, which peers they are passed on to
|
|
// and how far away we look to them, as the route servers of Internet
|
|
// exchanges and transit networks do. With L our own AS number, P a
|
|
// peer's, and G a group of sessions (`groups` of a peer):
|
|
//
|
|
// 0:P or L:0:P not to the peer with AS P
|
|
// L:P or L:1:P to the peer with AS P, and then only to peers
|
|
// named so
|
|
// 0:L or L:0:0 to nobody
|
|
// L:11:P with our AS once more on the path to the peer
|
|
// L:12:P with AS P; twice, three times. P 0 is every
|
|
// L:13:P peer in another AS.
|
|
// L:20:G not to the sessions of group G
|
|
// L:21:G to the sessions of group G, and then only to
|
|
// sessions named so, by group or AS
|
|
// L:31:G with our AS once more on the path to the
|
|
// L:32:G sessions of group G; twice, three times
|
|
// L:33:G
|
|
//
|
|
// A route with none of these goes to everyone it otherwise would. "Not"
|
|
// wins over "to". Of several prepends that apply, the most counts, on
|
|
// top of the session's export.as_path_prepend. The two-part form is a
|
|
// standard community, with room for AS numbers below 65536; the
|
|
// three-part forms are large communities and work for any.
|
|
//
|
|
// They are acted on where a route leaves our AS, and taken off there:
|
|
// to a peer in our own AS a route goes with them, for that router to act
|
|
// on. They are honoured on routes we originate too (`communities` and
|
|
// `large_communities` of `originate`), on what import.add_communities
|
|
// puts on, and on what a peer in our own AS, or one with
|
|
// import.accept_control_communities, sends. From any other peer the
|
|
// communities of our own AS are taken off as its routes come in, so that
|
|
// nobody outside can say what is done with our routes.
|
|
//
|
|
// With this on, standard communities L:n are taken for "to the peer
|
|
// with AS n": mark routes with something else (large communities
|
|
// L:100:n and up, say; functions 2 to 9 are left for marks too).
|
|
bool control_communities = 13;
|
|
|
|
// Graceful restart, for every peer that has no `graceful_restart` of its
|
|
// own. Left out, it is on, as the defaults below have it.
|
|
GracefulRestart graceful_restart = 14;
|
|
|
|
// Where this router passes on routes from one router of our AS to
|
|
// another (Peer.route_reflector_client), the cluster it does so for, as
|
|
// a dotted-quad: what it puts on such routes, and what it does not take
|
|
// back (RFC 4456). Give routers that serve the same clients the same
|
|
// cluster ID. Defaults to router_id.
|
|
string cluster_id = 15;
|
|
|
|
// Limits on what goes to other networks that are not our customers: to
|
|
// every peer whose role is PROVIDER, PEER or ROUTE_SERVER, and to one
|
|
// in another AS that has no role. Not to customers, route server
|
|
// clients or routers of our own AS. A peer's own `export_limits` takes
|
|
// the place of these.
|
|
//
|
|
// They hold whatever the routes are and wherever they came from, and
|
|
// whatever `export` says: a check on everything else, in case it goes
|
|
// wrong. With the roles, a route learned from a provider or a peer is
|
|
// passed on to customers only; these keep it from going further even
|
|
// if a route is not marked as it should be.
|
|
ExportLimits export_limits = 16;
|
|
|
|
// Names for communities, for the status page to show in place of the
|
|
// numbers: what the marks on routes mean to a reader. A name for one
|
|
// community ("64601:100:2" is "comrack"), or for a kind of them, with
|
|
// `*` for the part left open ("64601:102:*" is "interconnection"), which
|
|
// is shown with the open part after the name. The daemon itself does
|
|
// nothing with them.
|
|
repeated CommunityName community_names = 17;
|
|
}
|
|
|
|
// A name for a community, or for a kind of them.
|
|
message CommunityName {
|
|
// The community, standard ("64601:100") or large ("64601:100:2"), or a
|
|
// pattern of them with `*` for a part left open ("64601:102:*").
|
|
string community = 1;
|
|
// What it is shown as.
|
|
string name = 2;
|
|
}
|
|
|
|
// Limits on what is announced to a peer, which hold whatever `export`
|
|
// and the routes say.
|
|
message ExportLimits {
|
|
// Only routes for these prefixes are announced: our own address space
|
|
// and our customers', say, with max_length as long as the longest
|
|
// prefix announced from it. Routes for other prefixes, learned or
|
|
// originated, are not. Empty allows any.
|
|
repeated PrefixRange prefixes = 1;
|
|
|
|
// The most routes that are announced to the peer at a time. If more
|
|
// were to be, none of them is: the session is ended with a Cease /
|
|
// Administrative Shutdown NOTIFICATION that says why (RFC 9003), and the
|
|
// peer is kept down for its import.hold_down_seconds, as when it sends
|
|
// us too many. Set it somewhat above what is expected. Zero is no
|
|
// limit.
|
|
uint32 max_prefixes = 2;
|
|
}
|
|
|
|
// Graceful restart (RFC 4724): BGP restarting without the routes going.
|
|
//
|
|
// When the daemon is restarted in good order for an upgrade (on SIGUSR1),
|
|
// it leaves its routes in the kernel, and its peers keep the routes it
|
|
// announced to them, for as long as they were told a restart takes. When a
|
|
// peer restarts, its routes are kept and used as before, marked stale,
|
|
// until it has sent them again; those it does not send again are removed.
|
|
// Either way, nothing is withdrawn across the network for a restart.
|
|
//
|
|
// It is in use with a peer that offers it too. A session that ends with a
|
|
// Hard Reset (RFC 8538), or because of an error, has its routes removed at
|
|
// once, as without graceful restart.
|
|
message GracefulRestart {
|
|
// True does not offer graceful restart: a peer's routes are removed as
|
|
// soon as its session ends, and it removes ours as soon as it sees ours
|
|
// end.
|
|
optional bool disabled = 1;
|
|
|
|
// How long, in seconds, peers are told a restart of this daemon takes:
|
|
// how long they keep our routes after our session with them ends. At
|
|
// most 4095. Defaults to 120.
|
|
optional uint32 restart_time_seconds = 2;
|
|
|
|
// The longest time, in seconds, a restarting peer's routes are kept
|
|
// stale: while it is gone, whatever restart time it gave, and again once
|
|
// it is back, until it has sent all its routes. Zero keeps none.
|
|
// Defaults to 120.
|
|
optional uint32 stale_routes_seconds = 3;
|
|
}
|
|
|
|
// Installing routes in the kernel. Linux only; the daemon needs the
|
|
// CAP_NET_ADMIN capability.
|
|
//
|
|
// The best route of a prefix is installed if its next hop is a neighbor:
|
|
// an address in the network of one of the machine's interfaces. Routes
|
|
// are marked as BGP's ("proto bgp"), and every route with that mark, the
|
|
// table and the metric below is taken to be this daemon's: what it finds
|
|
// at startup and no longer wants, it removes. When the daemon stops in
|
|
// good order it removes its routes.
|
|
message Kernel {
|
|
// The routing table. Defaults to 254, the main table, which is the one
|
|
// packets are forwarded by unless rules say otherwise.
|
|
uint32 table = 1;
|
|
|
|
// The metric of the routes. Defaults to 20. Of several routes for a
|
|
// prefix the kernel uses the one with the lowest metric.
|
|
optional uint32 metric = 2;
|
|
|
|
// By default, where the kernel has nexthop objects (Linux 5.3 and
|
|
// later), a gateway is put there once as such an object and routes name
|
|
// it, which makes installing a full table about a third faster. `ip
|
|
// route` then shows routes with "nhid". True has every route carry its
|
|
// own gateway, as on older kernels.
|
|
bool without_nexthop_objects = 3;
|
|
|
|
// How long, after the daemon starts, routes of its own that an earlier
|
|
// run left in the kernel are kept though no peer has announced them
|
|
// (again). Defaults to 120. The daemon's table is empty until its peers
|
|
// have sent theirs; removing the old routes at once would stop the
|
|
// machine forwarding for as long as that takes. After this time, what
|
|
// was not announced again is removed.
|
|
// Zero removes them at once.
|
|
optional uint32 stale_seconds = 4;
|
|
|
|
// The kernel's table whose routes say how a next hop that is not a
|
|
// neighbour is reached: its connected and static routes, and an IGP's
|
|
// if there is one. Defaults to 254, the main table. A route whose next
|
|
// hop is covered by such a route is installed with that route's gateway
|
|
// and interface, the kernel not looking gateways up in turn. Routes put
|
|
// in the table by BGP, this daemon's or another's, never count: a next
|
|
// hop reached only by way of a BGP route rests on what may itself rest
|
|
// on a next hop.
|
|
uint32 resolution_table = 5;
|
|
|
|
// Whether the default route in that table counts as the way to a next
|
|
// hop. Off by default: on a router the default route points at a
|
|
// transit provider, and a next hop "reached" only by sending the
|
|
// packets to the Internet at large is not reached.
|
|
bool resolve_via_default_route = 6;
|
|
}
|
|
|
|
// Where to get the validated ROA payloads that say which AS may originate
|
|
// which prefixes. With this set, a route whose origin is not authorised
|
|
// for its prefix ("invalid") is refused, from every peer that is not in
|
|
// our own AS and does not have accept_rpki_invalid set. Routes that
|
|
// nothing is known about are taken as before.
|
|
//
|
|
// A validator that speaks version 2 of the protocol also gives the ASPAs,
|
|
// in which networks say who their providers are. With those, a route
|
|
// whose AS path cannot have come about by networks passing routes on as
|
|
// they should (a route leak, or a made-up path) is refused, from every
|
|
// peer that has a role set and does not have accept_aspa_invalid set.
|
|
message Rpki {
|
|
// The RPKI-to-Router servers (RFC 8210, draft-ietf-sidrops-8210bis) of
|
|
// one or more validators, such as Routinator, rpki-client with StayRTR,
|
|
// or FORT, in order of preference. The port is required. One is used at
|
|
// a time, over plain TCP: keep it on a network you trust.
|
|
repeated TcpEndpoint caches = 1;
|
|
|
|
// How often to ask the cache for changes unprompted, how long to wait
|
|
// before trying again after a failure, and how long the data may be used
|
|
// without a cache confirming it, after which nothing is invalid any
|
|
// more. Each defaults to what the cache says, or to 3600, 600 and 7200.
|
|
uint32 refresh_seconds = 2;
|
|
uint32 retry_seconds = 3;
|
|
uint32 expire_seconds = 4;
|
|
}
|
|
|
|
// A route originated by this router. It is announced with an AS_PATH of the
|
|
// local AS (empty, to a peer in our own 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). A peer at a link-local IPv6 address has the
|
|
// interface it is on after it: "fe80::1%eth0".
|
|
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).
|
|
// At least 3, or 0 for a session without keepalives that is never timed
|
|
// out. Defaults to 90 when unset.
|
|
optional 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;
|
|
|
|
// Which of the peer's routes are taken. Left out, the general checks
|
|
// apply and there is no limit and no list.
|
|
ImportPolicy import = 8;
|
|
|
|
// What the peer is to us. Not for a peer in our own AS. With it set:
|
|
//
|
|
// - Our OPEN says what we are to the peer, and a peer that says it is
|
|
// something else than configured here is refused (RFC 9234). One side
|
|
// having the other down as a customer and the other as a peer is how
|
|
// leaks come about.
|
|
// - Routes are marked "only to customer" as they come in from a provider,
|
|
// a peer or a route server, and as they go out to a customer, a peer
|
|
// or a route server client. A route with that mark that comes back up
|
|
// from a customer, or across from a second peer, is a leak and is
|
|
// refused. This cannot be turned off.
|
|
// - Where rpki is configured, the AS paths of the peer's routes are
|
|
// verified against the ASPAs: a route from a customer, a peer or a
|
|
// route server must have come up through providers all the way; one
|
|
// from a provider may have come up and then down.
|
|
//
|
|
// Left out, none of this is done for the peer.
|
|
Role role = 9;
|
|
|
|
// Refuse the peer unless its OPEN says what it is. By default a peer
|
|
// that says nothing (one that does not implement RFC 9234) is taken at
|
|
// this configuration's word for it. Needs role.
|
|
bool require_role = 10;
|
|
|
|
// What is announced to the peer, and how. Left out, the top-level
|
|
// `export` holds, and without that the routes we originate are
|
|
// announced as they are.
|
|
ExportPolicy export = 11;
|
|
|
|
// Graceful restart with this peer. What is set here takes the place of
|
|
// what the top-level `graceful_restart` says.
|
|
GracefulRestart graceful_restart = 12;
|
|
|
|
// The groups the session is in, by number, for control communities to
|
|
// name sessions by (see control_communities): those at one Internet
|
|
// exchange, say, or those over one link, whatever AS the peers are. Use
|
|
// the same numbers on all routers of the AS: a route marked on one is
|
|
// acted on by another. From 1.
|
|
repeated uint32 groups = 13;
|
|
|
|
// Pass on to this peer, a router of our own AS, the routes learned from
|
|
// our other routers, and pass on the routes it sends to all of them: we
|
|
// are its route reflector (RFC 4456). Without it, as BGP has it, a route
|
|
// learned from one router of our AS goes to no other, and every router
|
|
// needs a session with every other. Routes go with this router as next
|
|
// hop, so that the peer can reach what lies behind another router
|
|
// through this one. Only for a peer in our own AS: other networks are
|
|
// told of learned routes by `export` and the roles alone. The peer's
|
|
// `export` still has to pass on learned routes.
|
|
bool route_reflector_client = 14;
|
|
|
|
// Limits on what is announced to the peer, in the place of the
|
|
// top-level export_limits. They apply to the same peers as those do: to
|
|
// one whose role is PROVIDER, PEER or ROUTE_SERVER, or that is in
|
|
// another AS and has no role.
|
|
ExportLimits export_limits = 15;
|
|
|
|
// Do not open connections to the peer: wait for it to connect. The
|
|
// session is configured in full, and comes up when the peer connects
|
|
// from `endpoint`'s address; the port of `endpoint` is not used. For a
|
|
// new peer whose side is not ready yet, or one that is to open the
|
|
// connections itself.
|
|
bool passive = 16;
|
|
|
|
// About how many routes the peer sends when all is well: a full table,
|
|
// a few hundred from an exchange peer, one from a customer. Nothing is
|
|
// decided by it. The status page compares the routes the peer has in
|
|
// the table with it, and shows an established session with fewer than
|
|
// half as needing attention: a peer that is up but has sent next to
|
|
// nothing looks, without this, exactly like one that is fine. Zero, the
|
|
// default, compares nothing. The routing table is also made with room
|
|
// for the largest of these from the start, so that it need not grow,
|
|
// and so use twice its memory for a moment, while the tables come in.
|
|
uint32 expected_routes = 17;
|
|
}
|
|
|
|
// What is announced to a peer.
|
|
//
|
|
// The routes we originate are always announced. Routes learned from other
|
|
// peers are passed on only if learned_routes says so, and then only as
|
|
// far as these let them:
|
|
//
|
|
// - Never back to the peer a route came from, nor to a peer whose AS is
|
|
// on its path already.
|
|
// - A route from a peer in our own AS is not passed to another such peer,
|
|
// unless one of them is a route reflector client of ours
|
|
// (Peer.route_reflector_client).
|
|
// - Where peers have roles (RFC 9234): a route learned from a provider, a
|
|
// peer or a route server goes on to customers only. So with roles on
|
|
// all peers, turning this on makes us transit for our customers and for
|
|
// nobody else. Without roles there is no such rule, and every route
|
|
// goes to every peer: do not turn this on for a peer without a role
|
|
// unless that is what is wanted.
|
|
// - The communities NO_EXPORT and NO_ADVERTISE, and control_communities.
|
|
//
|
|
// A route is passed on with our AS added to its path and ourselves as
|
|
// next hop, without the MED it came with. To a peer in our own AS the
|
|
// path is left as it is and LOCAL_PREF goes along. To a peer whose role
|
|
// is ROUTE_SERVER_CLIENT the route goes as a route server sends it
|
|
// (RFC 7947): path, MED and, where the client can use it, next hop
|
|
// unchanged.
|
|
message ExportPolicy {
|
|
// Pass on the best routes learned from other peers.
|
|
bool learned_routes = 1;
|
|
|
|
// Communities put on every route announced to the peer: which router
|
|
// it went through, say. "64601:100", or a well-known name.
|
|
repeated string add_communities = 2;
|
|
|
|
// Large communities put on, as "64601:1:2".
|
|
repeated string add_large_communities = 3;
|
|
|
|
// Communities taken off first: one ("64601:100"), all of an AS
|
|
// ("64601:*"), or large ones with three parts ("64601:1:*").
|
|
repeated string remove_communities = 4;
|
|
|
|
// How many more times our AS is put on the path of every route
|
|
// announced to the peer, to make them look further away. At most 16.
|
|
uint32 as_path_prepend = 5;
|
|
}
|
|
|
|
// What a peer is to us.
|
|
enum Role {
|
|
ROLE_UNSPECIFIED = 0;
|
|
// We buy transit from the peer.
|
|
PROVIDER = 1;
|
|
// The peer buys transit from us.
|
|
CUSTOMER = 2;
|
|
// The peer and we exchange our own and our customers' routes.
|
|
PEER = 3;
|
|
// The peer is an Internet exchange's route server.
|
|
ROUTE_SERVER = 4;
|
|
// We are a route server and the peer is one of our clients.
|
|
ROUTE_SERVER_CLIENT = 5;
|
|
}
|
|
|
|
// What is taken from a peer. Every route is judged before it goes into
|
|
// the routing table. One that is refused is dropped, and so is the route
|
|
// it would have replaced.
|
|
//
|
|
// A route whose AS path holds our own AS number is always refused.
|
|
message ImportPolicy {
|
|
// The most routes the peer may have at a time. One more ends the session
|
|
// with Cease / Maximum Number of Prefixes Reached, and the peer is kept
|
|
// down for hold_down_seconds. Set it somewhat above what the peer is
|
|
// expected to send. Zero is no limit.
|
|
uint32 max_prefixes = 1;
|
|
|
|
// How long the peer is kept down after going over max_prefixes. Neither
|
|
// side's connections are taken meanwhile. Defaults to 600.
|
|
uint32 hold_down_seconds = 2;
|
|
|
|
// By default, prefixes that are not routed on the Internet are refused
|
|
// (private, loopback, link-local, documentation, multicast and reserved
|
|
// space), and so are routes with a reserved, private or documentation AS
|
|
// number anywhere in their path. True takes them.
|
|
bool accept_bogons = 3;
|
|
|
|
// By default a default route (0.0.0.0/0 or ::/0) is refused. True takes
|
|
// one, as from an upstream that is asked to send it.
|
|
bool accept_default_route = 4;
|
|
|
|
// The longest prefixes taken. Defaults to 24 and 48, the longest that are
|
|
// routed between networks.
|
|
uint32 max_ipv4_prefix_length = 5;
|
|
uint32 max_ipv6_prefix_length = 6;
|
|
|
|
// By default the AS path of a route has to begin with the peer's own AS
|
|
// number. True takes any, as is needed for an Internet exchange's route
|
|
// server, which does not put its AS on the path.
|
|
bool accept_any_first_as = 7;
|
|
|
|
// The longest AS path taken, counted in AS numbers. Defaults to 64.
|
|
uint32 max_as_path_length = 8;
|
|
|
|
// The prefixes the peer may announce. Empty allows any. This is the
|
|
// list generated for a peer from the routing registries (with bgpq4,
|
|
// say).
|
|
repeated PrefixRange prefixes = 9;
|
|
|
|
// The AS numbers the peer's routes may originate from: the last AS of
|
|
// the path. Empty allows any.
|
|
repeated uint32 origin_asns = 10;
|
|
|
|
// By default, where route origin validation is configured (rpki), a
|
|
// route that is invalid is refused. True takes it all the same.
|
|
bool accept_rpki_invalid = 11;
|
|
|
|
// By default, where the validator gives ASPAs and the peer has a role,
|
|
// a route whose AS path they find invalid is refused. True takes it all
|
|
// the same.
|
|
bool accept_aspa_invalid = 12;
|
|
|
|
// By default a route whose AS path has an AS_SET in it is refused: sets
|
|
// are deprecated (RFC 9774), and with one nobody can say where a route
|
|
// comes from. True takes such routes.
|
|
bool accept_as_sets = 13;
|
|
|
|
// By default the next hop of a route from another network has to be the
|
|
// peer itself, so that a peer can only draw traffic to itself and not
|
|
// send it to a third party. True takes any next hop packets can be sent
|
|
// to. Not needed for a peer whose role is ROUTE_SERVER, whose routes
|
|
// have its clients as next hops.
|
|
bool accept_third_party_next_hop = 14;
|
|
|
|
// Communities put on every route taken from the peer: where it was
|
|
// learned, say, for other routers of ours and for `export` to go by.
|
|
// "64601:100", or a well-known name.
|
|
repeated string add_communities = 15;
|
|
|
|
// Large communities put on, as "64601:1:2".
|
|
repeated string add_large_communities = 16;
|
|
|
|
// Communities taken off first: one ("64601:100"), all of an AS
|
|
// ("64601:*"), or large ones with three parts ("64601:1:*"). Marks that
|
|
// mean something to us are not to be taken on a peer's word.
|
|
repeated string remove_communities = 17;
|
|
|
|
// The LOCAL_PREF of the peer's routes: of two routes for a prefix the
|
|
// one with the higher is chosen, whatever else they have. Left out, 100.
|
|
optional uint32 local_pref = 18;
|
|
|
|
// By default the communities of our own AS (L:n and L:n:m; and 0:n,
|
|
// with control_communities on) are taken off the routes of a peer in
|
|
// another AS as they come in, before add_communities puts ours on: what
|
|
// they ask of us is not for others to ask. True keeps them, for a
|
|
// customer that is to steer its own routes with control communities, or
|
|
// a route server's client. Not for a peer in our own AS, whose routes
|
|
// keep them in any case.
|
|
bool accept_control_communities = 19;
|
|
|
|
// What is done to some of the routes, beyond what is done to all of
|
|
// them above. Each route that is taken is looked at by the rules in
|
|
// turn, and the first that holds for it is applied; the rest are not
|
|
// looked at. A rule sees the route as the statements above leave it:
|
|
// with our communities taken off and ours put on.
|
|
repeated ImportRule rules = 20;
|
|
|
|
// By default a route with the BLACKHOLE community (65535:666, RFC
|
|
// 7999), which asks for the traffic to its prefix to be dropped, is
|
|
// refused ("blackhole request"). True takes such a route if it is for
|
|
// one address (a /32 or /128), whatever the longest prefix taken
|
|
// otherwise, and inside what the peer may announce; its next hop is
|
|
// not looked at. The traffic to the address is then dropped by this
|
|
// router (a blackhole route in the kernel), and the route goes on to
|
|
// the peers the export policy sends it to, community and all, for them
|
|
// to do the same. For a customer under attack, and for a route server
|
|
// whose blackhole routes are to be honoured.
|
|
bool accept_blackholes = 21;
|
|
}
|
|
|
|
// What is done to the routes with some communities, or for some prefixes:
|
|
// those learned at one exchange, say, by the mark another router of ours
|
|
// put on them, to be preferred less; or one prefix of a customer's, to be
|
|
// marked for a prepend.
|
|
message ImportRule {
|
|
// The rule holds for routes with one of these communities: one
|
|
// ("64601:100"), all of an AS ("64601:*"), or large ones with three
|
|
// parts ("64601:101:*"). Left out, for routes with any.
|
|
repeated string match_communities = 1;
|
|
|
|
// And for routes for a prefix in these. Left out, for any prefix.
|
|
repeated PrefixRange match_prefixes = 2;
|
|
|
|
// The LOCAL_PREF of the routes, in place of import.local_pref.
|
|
optional uint32 local_pref = 3;
|
|
|
|
// Communities put on the routes.
|
|
repeated string add_communities = 4;
|
|
repeated string add_large_communities = 5;
|
|
}
|
|
|
|
// A prefix, and optionally the more specific prefixes inside it.
|
|
message PrefixRange {
|
|
// In CIDR notation, e.g. "193.0.0.0/21".
|
|
string prefix = 1;
|
|
// The longest prefix inside it that is also allowed. Left out, only the
|
|
// prefix itself is.
|
|
uint32 max_length = 2;
|
|
}
|
|
|
|
// 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;
|
|
// Offer to send the peer several routes for a prefix. As yet only the
|
|
// best is sent all the same.
|
|
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;
|
|
}
|