Skip to main content

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::{
26    path::fetcher::traits::PathFetchError,
27    stack::{scmp_handler::ScmpErrorReceiver, socket::SendErrorReceiver},
28};
29
30/// Trait for active path management with async interface.
31pub trait PathManager: SyncPathManager {
32    /// Returns a path to the destination from the path cache or requests a new path from the
33    /// SCION Control Plane.
34    fn path_wait(
35        &self,
36        src: IsdAsn,
37        dst: IsdAsn,
38        now: SystemTime,
39    ) -> impl Future<Output = Result<ScionPath, PathWaitError>> + Send + '_;
40
41    /// Returns a path to the destination from the path cache or requests a new path from the
42    /// SCION Control Plane, with a maximum wait time.
43    fn path_timeout(
44        &self,
45        src: IsdAsn,
46        dst: IsdAsn,
47        now: SystemTime,
48        timeout: Duration,
49    ) -> impl Future<Output = Result<ScionPath, PathWaitTimeoutError>> + Send + '_ {
50        let fut = self.path_wait(src, dst, now);
51        async move {
52            match tokio::time::timeout(timeout, fut).await {
53                Ok(result) => {
54                    result.map_err(|e| {
55                        match e {
56                            PathWaitError::FetchFailed(source) => {
57                                PathWaitTimeoutError::FetchFailed(source)
58                            }
59                            PathWaitError::NoPathFound => PathWaitTimeoutError::NoPathFound,
60                        }
61                    })
62                }
63                Err(_) => Err(PathWaitTimeoutError::Timeout),
64            }
65        }
66    }
67
68    /// Returns the receiver that can be used to report SCMP errors to the path manager.
69    /// Returns `None` if the path manager does not support receiving SCMP errors.
70    fn scmp_error_receiver(self: Arc<Self>) -> Option<Arc<dyn ScmpErrorReceiver>> {
71        None
72    }
73
74    /// Returns the receiver that can be used to report send errors to the path manager.
75    /// Returns `None` if the path manager does not support receiving send errors.
76    fn send_error_receiver(self: Arc<Self>) -> Option<Arc<dyn SendErrorReceiver>> {
77        None
78    }
79}
80
81/// Errors returned when waiting for a path to a destination.
82#[derive(Debug, Clone, Error)]
83#[non_exhaustive]
84pub enum PathWaitError {
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}
95
96/// Errors returned when waiting for a path to a destination with a timeout.
97#[derive(Debug, Clone, Error)]
98#[non_exhaustive]
99pub enum PathWaitTimeoutError {
100    /// Fetching a path from the configured segment sources failed.
101    ///
102    /// The error is shared (`Arc`) because a single fetch failure may be reported to multiple
103    /// concurrent waiters.
104    #[error("path fetch failed: {0}")]
105    FetchFailed(#[source] Arc<PathFetchError>),
106    /// No path to the destination was found.
107    #[error("no path found")]
108    NoPathFound,
109    /// Waiting for a path timed out.
110    #[error("waiting for path timed out")]
111    Timeout,
112}
113
114/// Trait for active path management with sync interface. Implementors of this trait should be
115/// able to be used in sync and async context. The functions must not block.
116pub trait SyncPathManager {
117    /// Add a path to the path cache. This can be used to register reverse paths.
118    fn register_path(&self, src: IsdAsn, dst: IsdAsn, now: SystemTime, path: ScionPath);
119
120    /// Returns a path to the destination from the path cache.
121    /// If the path is not in the cache, it returns Ok(None), possibly causing the path to be
122    /// fetched in the background. If the cache is locked an io error `WouldBlock` is
123    /// returned.
124    fn try_cached_path(
125        &self,
126        src: IsdAsn,
127        dst: IsdAsn,
128        now: SystemTime,
129    ) -> io::Result<Option<ScionPath>>;
130}
131
132/// Trait for prefetching paths in the path manager.
133pub trait PathPrefetcher {
134    /// Prefetch a path for the given source and destination.
135    fn prefetch_path(&self, src: IsdAsn, dst: IsdAsn);
136}