use chrono::{DateTime, Utc};
use derive_more::Display;
use scion_proto::{
address::{IsdAsn, ScionAddr},
packet::ScionPacketRaw,
scmp::ScmpErrorMessage,
};
use crate::network::scion::crypto::ForwardingKey;
pub mod spec;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ScionNetworkTime(pub u32);
impl ScionNetworkTime {
pub fn now() -> Self {
ScionNetworkTime(Utc::now().timestamp() as u32)
}
pub fn from_timestamp_secs(secs: u32) -> Self {
ScionNetworkTime(secs)
}
pub fn date_time(&self) -> DateTime<Utc> {
DateTime::<Utc>::from_timestamp(self.0 as i64, 0)
.expect("u32 timestamp can not be out of range")
}
pub fn inner(&self) -> u32 {
self.0
}
}
pub trait RoutingLogic {
fn route(
local_as: IsdAsn,
scion_packet: &mut ScionPacketRaw,
ingress_interface_id: u16,
now: ScionNetworkTime,
as_forwarding_key: &ForwardingKey,
interface_lookup: impl Fn(u16) -> Option<AsRoutingInterfaceState>,
) -> Result<AsRoutingAction, ScmpErrorMessage>;
}
impl From<Result<AsRoutingAction, ScmpErrorMessage>> for AsRoutingAction {
fn from(value: Result<AsRoutingAction, ScmpErrorMessage>) -> Self {
match value {
Ok(decision) => decision,
Err(err) => AsRoutingAction::Local(LocalAsRoutingAction::SendSCMPErrorResponse(err)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LocalAsRoutingAction {
IngressSCMPHandleRequest {
interface_id: u16,
},
EgressSCMPHandleRequest {
interface_id: u16,
},
ForwardLocal {
target_address: ScionAddr,
},
SendSCMPErrorResponse(ScmpErrorMessage),
}
impl From<LocalAsRoutingAction> for AsRoutingAction {
fn from(value: LocalAsRoutingAction) -> Self {
AsRoutingAction::Local(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AsRoutingAction {
Local(LocalAsRoutingAction),
ForwardNextHop {
link_interface_id: u16,
},
Drop,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AsRoutingInterfaceState {
pub(crate) link_type: AsRoutingLinkType,
pub(crate) is_up: bool,
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AsRoutingLinkType {
LinkToCore,
LinkToParent,
LinkToChild,
LinkToPeer,
}
impl AsRoutingLinkType {
pub fn reverse(&self) -> Self {
match self {
AsRoutingLinkType::LinkToCore => AsRoutingLinkType::LinkToCore,
AsRoutingLinkType::LinkToParent => AsRoutingLinkType::LinkToChild,
AsRoutingLinkType::LinkToChild => AsRoutingLinkType::LinkToParent,
AsRoutingLinkType::LinkToPeer => AsRoutingLinkType::LinkToPeer,
}
}
}