What was to be scripted is configuration, done natively:
- import { add_communities, add_large_communities, remove_communities,
local_pref }: every route taken from a peer is marked (where it was
learned, say), with nobody else's word for our marks taken, and given
its preference, which selection goes by.
- export { add_communities, add_large_communities, remove_communities,
as_path_prepend, learned_routes }, for a peer or for all that have none
of their own.
- control_communities: the communities by which routes say which peers
they are passed on to, as exchanges' route servers have them (0:P, L:P,
0:L, and the large forms L:0:P, L:1:P, L:0:0), taken off as the route
goes on.
And what the last of these is for: with export.learned_routes a peer is
told the best route of every prefix the others announced. The rules are
BGP's and cannot be turned off: not back where it came from, not to a
peer whose AS is on the path, not between two internal peers, not past
NO_EXPORT or NO_ADVERTISE; our AS on the path and ourselves as next hop
to another network, LOCAL_PREF to our own; to a route server's client
the path, MED and next hop as they came (RFC 7947). Which routes go where
follows from the roles of RFC 9234: a route that came down or across goes
on down only, so that with roles on every peer this makes us transit for
our customers and nothing else. A peer without a role is told everything,
and the daemon says so at startup.
Each session follows the table's best routes with a reader and keeps the
prefixes it has announced, so that it can withdraw them. Routes that go
out alike go in one UPDATE: changes are gathered for 50 ms first, and a
table that is given out anew is gathered whole (at most four sessions at
a time; it is tens of megabytes). For that to work the table's journal
had to give out together what was written together: every change now
carries a time on a table-wide clock, a reader's pass reads every shard
up to one time, no further than the changes that are complete in every
shard, and a resync takes its places in the journals as of one time.
One peer sending 1.23 M routes over a session, another told of them:
in our table after 0.47 s, all heard after 2.1 s, four routes an UPDATE.
The lab has a phase, transit: FRR as our customer and BIRD as our
provider, routes each way with the right paths and marks, one kept back
by a community, and pings between their networks through us.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
47 lines
1.0 KiB
TOML
47 lines
1.0 KiB
TOML
[package]
|
|
name = "bgp-bench"
|
|
description = "Benchmarks at the scale of the Internet routing table"
|
|
authors.workspace = true
|
|
edition.workspace = true
|
|
homepage.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
version.workspace = true
|
|
publish = false
|
|
|
|
[dependencies]
|
|
bgp-packet.workspace = true
|
|
bgp-primitives.workspace = true
|
|
bytes.workspace = true
|
|
flate2 = "1"
|
|
stats_alloc = { version = "0.1.10", optional = true }
|
|
|
|
[dev-dependencies]
|
|
bgp-integration-tests.workspace = true
|
|
bgp-rib.workspace = true
|
|
bgp-server.workspace = true
|
|
tokio.workspace = true
|
|
tracing.workspace = true
|
|
tracing-subscriber.workspace = true
|
|
|
|
[features]
|
|
# Counts every allocation, to report how much memory a table holds. The
|
|
# counters are shared by all threads and slow them down, so timings are
|
|
# taken without this and memory is measured in a run of its own.
|
|
count-memory = ["dep:stats_alloc"]
|
|
|
|
[[bench]]
|
|
name = "full_table"
|
|
harness = false
|
|
|
|
[[bench]]
|
|
name = "real_table"
|
|
harness = false
|
|
|
|
[[bench]]
|
|
name = "transit"
|
|
harness = false
|
|
|
|
[lints]
|
|
workspace = true
|