scion_stack/path/manager/traits.rs
1// Copyright 2025 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{
16 future::Future,
17 io,
18 sync::Arc,
19 time::{Duration, SystemTime},
20};
21
22use sciparse::{identifier::isd_asn::IsdAsn, path::ScionPath};
23use thiserror::Error;
24
25use crate::path::fetcher::traits::PathFetchError;
26
27/// Trait for active path management with async interface.
28pub trait PathManager: SyncPathManager {
29 /// Returns a path to the destination from the path cache or requests a new path from the
30 /// SCION Control Plane.
31 fn path_wait(
32 &self,
33 src: IsdAsn,
34 dst: IsdAsn,
35 now: SystemTime,
36 ) -> impl Future<Output = Result<ScionPath, PathWaitError>> + Send + '_;
37
38 /// Returns a path to the destination from the path cache or requests a new path from the
39 /// SCION Control Plane, with a maximum wait time.
40 fn path_timeout(
41 &self,
42 src: IsdAsn,
43 dst: IsdAsn,
44 now: SystemTime,
45 timeout: Duration,
46 ) -> impl Future<Output = Result<ScionPath, PathWaitTimeoutError>> + Send + '_ {
47 let fut = self.path_wait(src, dst, now);
48 async move {
49 match tokio::time::timeout(timeout, fut).await {
50 Ok(result) => {
51 result.map_err(|e| {
52 match e {
53 PathWaitError::FetchFailed(source) => {
54 PathWaitTimeoutError::FetchFailed(source)
55 }
56 PathWaitError::NoPathFound => PathWaitTimeoutError::NoPathFound,
57 }
58 })
59 }
60 Err(_) => Err(PathWaitTimeoutError::Timeout),
61 }
62 }
63 }
64}
65
66/// Errors returned when waiting for a path to a destination.
67#[derive(Debug, Clone, Error)]
68#[non_exhaustive]
69pub enum PathWaitError {
70 /// Fetching a path from the configured segment sources failed.
71 ///
72 /// The error is shared (`Arc`) because a single fetch failure may be reported to multiple
73 /// concurrent waiters.
74 #[error("path fetch failed: {0}")]
75 FetchFailed(#[source] Arc<PathFetchError>),
76 /// No path to the destination was found.
77 #[error("no path found")]
78 NoPathFound,
79}
80
81/// Errors returned when waiting for a path to a destination with a timeout.
82#[derive(Debug, Clone, Error)]
83#[non_exhaustive]
84pub enum PathWaitTimeoutError {
85 /// Fetching a path from the configured segment sources failed.
86 ///
87 /// The error is shared (`Arc`) because a single fetch failure may be reported to multiple
88 /// concurrent waiters.
89 #[error("path fetch failed: {0}")]
90 FetchFailed(#[source] Arc<PathFetchError>),
91 /// No path to the destination was found.
92 #[error("no path found")]
93 NoPathFound,
94 /// Waiting for a path timed out.
95 #[error("waiting for path timed out")]
96 Timeout,
97}
98
99/// Trait for active path management with sync interface. Implementors of this trait should be
100/// able to be used in sync and async context. The functions must not block.
101pub trait SyncPathManager {
102 /// Add a path to the path cache. This can be used to register reverse paths.
103 fn register_path(&self, src: IsdAsn, dst: IsdAsn, now: SystemTime, path: ScionPath);
104
105 /// Returns a path to the destination from the path cache.
106 /// If the path is not in the cache, it returns Ok(None), possibly causing the path to be
107 /// fetched in the background. If the cache is locked an io error `WouldBlock` is
108 /// returned.
109 fn try_cached_path(
110 &self,
111 src: IsdAsn,
112 dst: IsdAsn,
113 now: SystemTime,
114 ) -> io::Result<Option<ScionPath>>;
115}
116
117/// Trait for prefetching paths in the path manager.
118pub trait PathPrefetcher {
119 /// Prefetch a path for the given source and destination.
120 fn prefetch_path(&self, src: IsdAsn, dst: IsdAsn);
121}