Code health after review: docs, metrics, structure, one more fuzz target
What the code-health review found, and what a fuzz target written for it
found in its first seconds.
- A set of attributes with the same attribute twice is refused by the
routing table. Its readers (the selection key, the path, the next hop)
could each take a different one of the two. The decoder never lets one
through; the new fuzz target `attrs` found that the table would.
- bgp_peer_up{peer}, to alert on a peer going away, and bgp_build_info.
Every metric is there from the first scrape. Alerts for a peer down,
hijack attempts and kernel errors are in the README.
- `bgp --check config` validates a configuration without starting, and
`--version` says which build it is. CI runs the first on the example
configuration, which a test now also parses with its commented fields
put in; the example had to learn about the next hop check.
- Path attributes have a module of their own, packet::attributes,
re-exported from packet::message as before.
- policy::From, which shadowed the trait, is RouteSource. The server's
connection, dialer and fsm modules are private. Logging arguments live
in the binary; the server library no longer depends on clap.
- One is_unicast_link_local (the standard library's) instead of two of
our own; SelectionKey::origin(); one place where an Import is made.
- READMEs say what the daemon does today rather than what it did not do
a year ago. Documentation links are checked in CI. Unused dependencies
and bgp_web::serve are gone; the Docker build is --locked and does not
ship the fuzz corpus.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ca86ede2f
commit
3d946c32ce
41 files changed
+1323
-1102
No files matched your search
@@ -27,7 +27,8 @@ const MAX_AS_PATH_PREPEND: u32 = 16;
|
||||
pub struct Config {
|
||||
pub router_id: Ipv4Addr,
|
||||
pub local_asn: u32,
|
||||
/// Default hold time advertised to peers that have no per-peer override.
|
||||
/// The hold time offered to a peer that is not in the configuration
|
||||
/// (see `accept_unconfigured_peers`). Configured peers have their own.
|
||||
pub hold_time_secs: u16,
|
||||
pub listen_endpoints: Vec<SocketAddr>,
|
||||
pub peers: Vec<PeerConfig>,
|
||||
@@ -461,6 +462,45 @@ mod tests {
|
||||
parse(text).err().expect(text)
|
||||
}
|
||||
|
||||
/// The example that the documentation points to, and that operators
|
||||
/// start from: as it is, and with what it shows commented out put in.
|
||||
#[test]
|
||||
fn the_example_configuration_is_in_order() {
|
||||
let example = include_str!("../../../testdata/server.textpb");
|
||||
let config = parse(example).expect("the example as it is");
|
||||
assert_eq!(config.peers.len(), 1);
|
||||
assert!(config.peers[0].import.accept_third_party_next_hop);
|
||||
assert!(config.rpki.is_none() && config.kernel.is_none());
|
||||
|
||||
// A commented line that is a field, or a block on one line, is
|
||||
// configuration shown for the taking.
|
||||
let shown: String = example
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let (indent, rest) = line.split_at(line.len() - line.trim_start().len());
|
||||
let field = rest.strip_prefix("# ").filter(|field| {
|
||||
let name_ends = field.find([':', ' ']).unwrap_or(0);
|
||||
let is_name = name_ends > 0
|
||||
&& field[..name_ends]
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_lowercase() || c == '_');
|
||||
let after = &field[name_ends..];
|
||||
is_name
|
||||
&& (after.starts_with(": ") && !after[2..].contains(' ')
|
||||
|| after.starts_with(" {") && after.ends_with('}'))
|
||||
});
|
||||
format!("{indent}{}\n", field.unwrap_or(rest))
|
||||
})
|
||||
.collect();
|
||||
assert_ne!(shown, example, "nothing was taken for configuration");
|
||||
let config = parse(&shown).unwrap_or_else(|e| panic!("{e}\n{shown}"));
|
||||
assert!(config.rpki.is_some(), "{shown}");
|
||||
assert!(config.kernel.is_some(), "{shown}");
|
||||
assert_eq!(config.peers[0].role, Some(PeerRole::Peer));
|
||||
assert!(config.peers[0].require_role);
|
||||
assert!(config.peers[0].import.prefixes.is_some());
|
||||
}
|
||||
|
||||
const BASE: &str = "router_id: \"192.0.2.1\" local_asn: 65000\n";
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user