Kernel and RPKI: say what went wrong, and once
The RPKI client had one Timeout error whose text said "did not answer within 60s" whatever had run out: the connect timeout, the time for a whole answer, or the data's lifetime. These are what /api/rpki shows as the last error; each is its own now. The protocol version shown is the one the cache answered in, not the one being tried. The VRP set, hashed by the hundred thousand with every answer, uses the quick hash the ASPA table already did. In the kernel installer the writer task's error was worked out in three places, and the next-hop resolution checked for our own networks twice on every cache miss. A refusal was logged twice, once with the status lock held. The interfaces are listed in order of index by the structure that holds them, from a function that can be tested on any OS, and is. EIO is with the other errnos; Plan has no installed_prefixes (no callers) and clears its records in one place, with the order of Unresolved::ALL asserted at compile time since indexing depends on it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
3b22e318a2
commit
b467b136e4
8 files changed
+179
-111
No files matched your search
+26
-18
@@ -12,8 +12,8 @@ use bgp_primitives::ip_prefix::IpPrefix;
|
||||
use crate::interfaces::Interfaces;
|
||||
|
||||
// Asked for every route: a quick hash matters here.
|
||||
type HashMap<K, V> = std::collections::HashMap<K, V, foldhash::fast::RandomState>;
|
||||
type HashSet<K> = std::collections::HashSet<K, foldhash::fast::RandomState>;
|
||||
pub(crate) type HashMap<K, V> = std::collections::HashMap<K, V, foldhash::fast::RandomState>;
|
||||
pub(crate) type HashSet<K> = std::collections::HashSet<K, foldhash::fast::RandomState>;
|
||||
|
||||
/// Where the kernel is to send packets for a prefix.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@@ -63,6 +63,16 @@ impl Unresolved {
|
||||
}
|
||||
}
|
||||
|
||||
// A reason's place in `ALL` is its number as declared, which is what
|
||||
// [`Plan`] counts them by.
|
||||
const _: () = {
|
||||
let mut at = 0;
|
||||
while at < Unresolved::ALL.len() {
|
||||
assert!(Unresolved::ALL[at] as usize == at);
|
||||
at += 1;
|
||||
}
|
||||
};
|
||||
|
||||
/// The peer a route was learned from, as far as its next hop is concerned.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Neighbor {
|
||||
@@ -259,12 +269,19 @@ impl Plan {
|
||||
Some(reason) => self.unresolved.insert(prefix, reason),
|
||||
None => self.unresolved.remove(&prefix),
|
||||
};
|
||||
for (reason, by) in [(before, -1isize), (reason, 1)] {
|
||||
if let Some(reason) = reason {
|
||||
let count = &mut self.unresolved_counts[reason as usize];
|
||||
*count = count.wrapping_add_signed(by);
|
||||
}
|
||||
if let Some(before) = before {
|
||||
self.unresolved_counts[before as usize] -= 1;
|
||||
}
|
||||
if let Some(reason) = reason {
|
||||
self.unresolved_counts[reason as usize] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Forgets which prefixes are unresolved or refused, and why.
|
||||
fn forget_unresolved_and_refused(&mut self) {
|
||||
self.unresolved.clear();
|
||||
self.unresolved_counts = [0; Unresolved::ALL.len()];
|
||||
self.refused.clear();
|
||||
}
|
||||
|
||||
/// How many prefixes have a best route that the kernel refused.
|
||||
@@ -272,11 +289,6 @@ impl Plan {
|
||||
self.refused.len()
|
||||
}
|
||||
|
||||
/// The prefixes of the routes the kernel has.
|
||||
pub fn installed_prefixes(&self) -> impl Iterator<Item = &IpPrefix> {
|
||||
self.installed.keys()
|
||||
}
|
||||
|
||||
/// Notes a route of ours that the kernel already has. It stays only if
|
||||
/// the routing table turns out to have the same.
|
||||
///
|
||||
@@ -326,9 +338,7 @@ impl Plan {
|
||||
for entry in self.installed.values_mut() {
|
||||
entry.confirmed = false;
|
||||
}
|
||||
self.unresolved.clear();
|
||||
self.unresolved_counts = [0; Unresolved::ALL.len()];
|
||||
self.refused.clear();
|
||||
self.forget_unresolved_and_refused();
|
||||
}
|
||||
|
||||
/// The best route for `prefix` is now one that resolves as `target`.
|
||||
@@ -412,9 +422,7 @@ impl Plan {
|
||||
|
||||
/// Everything goes: the changes that empty the kernel of our routes.
|
||||
pub fn clear(&mut self) -> Vec<Op> {
|
||||
self.unresolved.clear();
|
||||
self.unresolved_counts = [0; Unresolved::ALL.len()];
|
||||
self.refused.clear();
|
||||
self.forget_unresolved_and_refused();
|
||||
self.installed
|
||||
.drain()
|
||||
.map(|(prefix, _)| Op::Remove { prefix })
|
||||
|
||||
Reference in new issue
Block a user