route caching
This commit is contained in:
parent
bf9cfd5b94
commit
26311e96c5
@ -65,14 +65,14 @@ deps-linux:
|
|||||||
# Code + Linux deps
|
# Code + Linux deps
|
||||||
code-linux:
|
code-linux:
|
||||||
FROM +deps-linux
|
FROM +deps-linux
|
||||||
COPY --dir .cargo external files scripts veilid-cli veilid-core veilid-server veilid-flutter veilid-wasm Cargo.lock Cargo.toml /veilid
|
COPY --dir .cargo external files scripts veilid-cli veilid-core veilid-server veilid-tools veilid-flutter veilid-wasm Cargo.lock Cargo.toml /veilid
|
||||||
RUN cat /veilid/scripts/earthly/cargo-linux/config.toml >> /veilid/.cargo/config.tml
|
RUN cat /veilid/scripts/earthly/cargo-linux/config.toml >> /veilid/.cargo/config.tml
|
||||||
WORKDIR /veilid
|
WORKDIR /veilid
|
||||||
|
|
||||||
# Code + Linux + Android deps
|
# Code + Linux + Android deps
|
||||||
code-android:
|
code-android:
|
||||||
FROM +deps-android
|
FROM +deps-android
|
||||||
COPY --dir .cargo external files scripts veilid-cli veilid-core veilid-server veilid-flutter veilid-wasm Cargo.lock Cargo.toml /veilid
|
COPY --dir .cargo external files scripts veilid-cli veilid-core veilid-server veilid-tools veilid-flutter veilid-wasm Cargo.lock Cargo.toml /veilid
|
||||||
RUN cat /veilid/scripts/earthly/cargo-linux/config.toml >> /veilid/.cargo/config.tml
|
RUN cat /veilid/scripts/earthly/cargo-linux/config.toml >> /veilid/.cargo/config.tml
|
||||||
RUN cat /veilid/scripts/earthly/cargo-android/config.toml >> /veilid/.cargo/config.tml
|
RUN cat /veilid/scripts/earthly/cargo-android/config.toml >> /veilid/.cargo/config.tml
|
||||||
WORKDIR /veilid
|
WORKDIR /veilid
|
||||||
|
@ -10,6 +10,16 @@ const REMOTE_PRIVATE_ROUTE_CACHE_SIZE: usize = 1024;
|
|||||||
const REMOTE_PRIVATE_ROUTE_CACHE_EXPIRY: TimestampDuration = TimestampDuration::new(300_000_000u64);
|
const REMOTE_PRIVATE_ROUTE_CACHE_EXPIRY: TimestampDuration = TimestampDuration::new(300_000_000u64);
|
||||||
/// Amount of time a route can remain idle before it gets tested
|
/// Amount of time a route can remain idle before it gets tested
|
||||||
const ROUTE_MIN_IDLE_TIME_MS: u32 = 30_000;
|
const ROUTE_MIN_IDLE_TIME_MS: u32 = 30_000;
|
||||||
|
/// The size of the compiled route cache
|
||||||
|
const COMPILED_ROUTE_CACHE_SIZE: usize = 256;
|
||||||
|
|
||||||
|
|
||||||
|
// Compiled route key for caching
|
||||||
|
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct CompiledRouteCacheKey {
|
||||||
|
sr_pubkey: DHTKey,
|
||||||
|
pr_pubkey: DHTKey,
|
||||||
|
}
|
||||||
|
|
||||||
/// Compiled route (safety route + private route)
|
/// Compiled route (safety route + private route)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -239,6 +249,8 @@ pub struct RouteSpecStoreCache {
|
|||||||
hop_cache: HashSet<Vec<u8>>,
|
hop_cache: HashSet<Vec<u8>>,
|
||||||
/// Has a remote private route responded to a question and when
|
/// Has a remote private route responded to a question and when
|
||||||
remote_private_route_cache: LruCache<DHTKey, RemotePrivateRouteInfo>,
|
remote_private_route_cache: LruCache<DHTKey, RemotePrivateRouteInfo>,
|
||||||
|
/// Compiled route cache
|
||||||
|
compiled_route_cache: LruCache<CompiledRouteCacheKey, SafetyRoute>,
|
||||||
/// List of dead allocated routes
|
/// List of dead allocated routes
|
||||||
dead_routes: Vec<DHTKey>,
|
dead_routes: Vec<DHTKey>,
|
||||||
/// List of dead remote routes
|
/// List of dead remote routes
|
||||||
@ -252,6 +264,7 @@ impl Default for RouteSpecStoreCache {
|
|||||||
used_end_nodes: Default::default(),
|
used_end_nodes: Default::default(),
|
||||||
hop_cache: Default::default(),
|
hop_cache: Default::default(),
|
||||||
remote_private_route_cache: LruCache::new(REMOTE_PRIVATE_ROUTE_CACHE_SIZE),
|
remote_private_route_cache: LruCache::new(REMOTE_PRIVATE_ROUTE_CACHE_SIZE),
|
||||||
|
compiled_route_cache: LruCache::new(COMPILED_ROUTE_CACHE_SIZE),
|
||||||
dead_routes: Default::default(),
|
dead_routes: Default::default(),
|
||||||
dead_remote_routes: Default::default(),
|
dead_remote_routes: Default::default(),
|
||||||
}
|
}
|
||||||
@ -1106,11 +1119,18 @@ impl RouteSpecStore {
|
|||||||
/// Release an allocated or remote route that is no longer in use
|
/// Release an allocated or remote route that is no longer in use
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
pub fn release_route(&self, key: &DHTKey) -> bool {
|
pub fn release_route(&self, key: &DHTKey) -> bool {
|
||||||
|
|
||||||
let is_remote = {
|
let is_remote = {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
|
|
||||||
|
// Release from compiled route cache if it's used there
|
||||||
|
self.invalidate_compiled_route_cache(inner, key);
|
||||||
|
|
||||||
|
// Check to see if this is a remote route
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
Self::with_peek_remote_private_route(inner, cur_ts, key, |_| {}).is_some()
|
Self::with_peek_remote_private_route(inner, cur_ts, key, |_| {}).is_some()
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_remote {
|
if is_remote {
|
||||||
self.release_remote_private_route(key)
|
self.release_remote_private_route(key)
|
||||||
} else {
|
} else {
|
||||||
@ -1222,6 +1242,41 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Route cache
|
||||||
|
fn add_to_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, pr_pubkey: DHTKey, safety_route: SafetyRoute)
|
||||||
|
{
|
||||||
|
let key = CompiledRouteCacheKey {
|
||||||
|
sr_pubkey: safety_route.public_key,
|
||||||
|
pr_pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(v) = inner.cache.compiled_route_cache.insert(key, safety_route) {
|
||||||
|
log_rtab!(error "route cache already contained key: sr_pubkey={:?}, pr_pubkey={:?}", v.public_key, pr_pubkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, sr_pubkey: DHTKey, pr_pubkey: DHTKey) -> Option<SafetyRoute> {
|
||||||
|
|
||||||
|
let key = CompiledRouteCacheKey {
|
||||||
|
sr_pubkey,
|
||||||
|
pr_pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
|
inner.cache.compiled_route_cache.get(&key).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidate_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, dead_key: &DHTKey) {
|
||||||
|
let mut dead_entries = Vec::new();
|
||||||
|
for (k, _v) in inner.cache.compiled_route_cache.iter() {
|
||||||
|
if k.sr_pubkey == *dead_key || k.pr_pubkey == *dead_key {
|
||||||
|
dead_entries.push(k.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for d in dead_entries {
|
||||||
|
inner.cache.compiled_route_cache.remove(&d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Compiles a safety route to the private route, with caching
|
/// Compiles a safety route to the private route, with caching
|
||||||
/// Returns an Err() if the parameters are wrong
|
/// Returns an Err() if the parameters are wrong
|
||||||
/// Returns Ok(None) if no allocation could happen at this time (not an error)
|
/// Returns Ok(None) if no allocation could happen at this time (not an error)
|
||||||
@ -1234,6 +1289,7 @@ impl RouteSpecStore {
|
|||||||
let routing_table = self.unlocked_inner.routing_table.clone();
|
let routing_table = self.unlocked_inner.routing_table.clone();
|
||||||
let rti = &mut *routing_table.inner.write();
|
let rti = &mut *routing_table.inner.write();
|
||||||
|
|
||||||
|
let pr_pubkey = private_route.public_key;
|
||||||
let pr_hopcount = private_route.hop_count as usize;
|
let pr_hopcount = private_route.hop_count as usize;
|
||||||
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
||||||
// Check private route hop count isn't larger than the max route hop count plus one for the 'first hop' header
|
// Check private route hop count isn't larger than the max route hop count plus one for the 'first hop' header
|
||||||
@ -1293,12 +1349,45 @@ impl RouteSpecStore {
|
|||||||
};
|
};
|
||||||
sr_pubkey
|
sr_pubkey
|
||||||
};
|
};
|
||||||
let safety_rsd = Self::detail_mut(inner, &sr_pubkey).unwrap();
|
|
||||||
|
|
||||||
// xxx implement caching here!
|
// Look up a few things from the safety route detail we want for the compiled route and don't borrow inner
|
||||||
|
let (optimize, first_hop, secret) = {
|
||||||
|
let safety_rsd = Self::detail(inner, &sr_pubkey).ok_or_else(|| eyre!("route missing"))?;
|
||||||
|
|
||||||
|
// We can optimize the peer info in this safety route if it has been successfully
|
||||||
|
// communicated over either via an outbound test, or used as a private route inbound
|
||||||
|
// and we are replying over the same route as our safety route outbound
|
||||||
|
let optimize = safety_rsd.stats.last_tested_ts.is_some() || safety_rsd.stats.last_received_ts.is_some();
|
||||||
|
|
||||||
|
// Get the first hop noderef of the safety route
|
||||||
|
let mut first_hop = safety_rsd.hop_node_refs.first().unwrap().clone();
|
||||||
|
// Ensure sequencing requirement is set on first hop
|
||||||
|
first_hop.set_sequencing(safety_spec.sequencing);
|
||||||
|
|
||||||
|
// Get the safety route secret key
|
||||||
|
let secret = safety_rsd.secret_key;
|
||||||
|
|
||||||
|
(optimize, first_hop, secret)
|
||||||
|
};
|
||||||
|
|
||||||
|
// See if we have a cached route we can use
|
||||||
|
if optimize {
|
||||||
|
if let Some(safety_route) = self.lookup_compiled_route_cache(inner, sr_pubkey, pr_pubkey) {
|
||||||
|
// Build compiled route
|
||||||
|
let compiled_route = CompiledRoute {
|
||||||
|
safety_route,
|
||||||
|
secret,
|
||||||
|
first_hop,
|
||||||
|
};
|
||||||
|
// Return compiled route
|
||||||
|
return Ok(Some(compiled_route));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create hops
|
// Create hops
|
||||||
let hops = {
|
let hops = {
|
||||||
|
let safety_rsd = Self::detail(inner, &sr_pubkey).ok_or_else(|| eyre!("route missing"))?;
|
||||||
|
|
||||||
// start last blob-to-encrypt data off as private route
|
// start last blob-to-encrypt data off as private route
|
||||||
let mut blob_data = {
|
let mut blob_data = {
|
||||||
let mut pr_message = ::capnp::message::Builder::new_default();
|
let mut pr_message = ::capnp::message::Builder::new_default();
|
||||||
@ -1311,12 +1400,6 @@ impl RouteSpecStore {
|
|||||||
blob_data
|
blob_data
|
||||||
};
|
};
|
||||||
|
|
||||||
// We can optimize the peer info in this safety route if it has been successfully
|
|
||||||
// communicated over either via an outbound test, or used as a private route inbound
|
|
||||||
// and we are replying over the same route as our safety route outbound
|
|
||||||
let optimize = safety_rsd.stats.last_tested_ts.is_some()
|
|
||||||
|| safety_rsd.stats.last_received_ts.is_some();
|
|
||||||
|
|
||||||
// Encode each hop from inside to outside
|
// Encode each hop from inside to outside
|
||||||
// skips the outermost hop since that's entering the
|
// skips the outermost hop since that's entering the
|
||||||
// safety route and does not include the dialInfo
|
// safety route and does not include the dialInfo
|
||||||
@ -1402,20 +1485,18 @@ impl RouteSpecStore {
|
|||||||
hops,
|
hops,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut first_hop = safety_rsd.hop_node_refs.first().unwrap().clone();
|
// Add to cache but only if we have an optimized route
|
||||||
|
if optimize {
|
||||||
// Ensure sequencing requirement is set on first hop
|
self.add_to_compiled_route_cache(inner, pr_pubkey, safety_route.clone());
|
||||||
first_hop.set_sequencing(safety_spec.sequencing);
|
}
|
||||||
|
|
||||||
// Build compiled route
|
// Build compiled route
|
||||||
let compiled_route = CompiledRoute {
|
let compiled_route = CompiledRoute {
|
||||||
safety_route,
|
safety_route,
|
||||||
secret: safety_rsd.secret_key,
|
secret,
|
||||||
first_hop,
|
first_hop,
|
||||||
};
|
};
|
||||||
|
|
||||||
// xxx: add cache here
|
|
||||||
|
|
||||||
// Return compiled route
|
// Return compiled route
|
||||||
Ok(Some(compiled_route))
|
Ok(Some(compiled_route))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user