Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add datagram trait and path-aware datagram #106

Merged
merged 6 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions crates/scion-proto/src/address/scion_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ impl ScionAddr {
}
}

impl AsRef<IsdAsn> for ScionAddr {
fn as_ref(&self) -> &IsdAsn {
match self {
ScionAddr::V4(addr) => addr.as_ref(),
ScionAddr::V6(addr) => addr.as_ref(),
ScionAddr::Svc(addr) => addr.as_ref(),
}
}
}

macro_rules! impl_from {
($base:ty, $variant:expr) => {
impl From<$base> for ScionAddr {
Expand Down Expand Up @@ -155,6 +165,12 @@ macro_rules! scion_address {
}
}

impl AsRef<IsdAsn> for $name {
fn as_ref(&self) -> &IsdAsn {
&self.isd_asn
}
}

impl core::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{},{}", self.isd_asn(), self.host())
Expand Down
16 changes: 16 additions & 0 deletions crates/scion-proto/src/address/socket_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ impl SocketAddr {
}
}

impl AsRef<IsdAsn> for SocketAddr {
fn as_ref(&self) -> &IsdAsn {
match self {
SocketAddr::V4(addr) => addr.as_ref(),
SocketAddr::V6(addr) => addr.as_ref(),
SocketAddr::Svc(addr) => addr.as_ref(),
}
}
}

impl From<SocketAddrV4> for SocketAddr {
/// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
#[inline]
Expand Down Expand Up @@ -244,6 +254,12 @@ macro_rules! socket_address {
Ok(Self {scion_addr, port })
}
}

impl AsRef<IsdAsn> for $name {
fn as_ref(&self) -> &IsdAsn {
self.scion_addr.as_ref()
}
}
};
}

Expand Down
14 changes: 7 additions & 7 deletions crates/scion-proto/src/datagram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub enum UdpEncodeError {
///
/// [RFC]: https://www.ietf.org/archive/id/draft-dekater-scion-dataplane-00.html
#[derive(Debug, Default, PartialEq)]
pub struct UdpDatagram {
pub struct UdpMessage {
/// The source and destination ports
pub port: ByEndpoint<u16>,
/// The length of the header and payload
Expand All @@ -41,7 +41,7 @@ pub struct UdpDatagram {
pub payload: Bytes,
}

impl UdpDatagram {
impl UdpMessage {
/// SCION protocol number for UDP.
///
/// See the [IETF SCION-dataplane RFC draft][rfc] for possible values.
Expand Down Expand Up @@ -89,7 +89,7 @@ impl UdpDatagram {
}
}

impl WireEncodeVec<2> for UdpDatagram {
impl WireEncodeVec<2> for UdpMessage {
type Error = InadequateBufferSize;

fn encode_with_unchecked(&self, buffer: &mut BytesMut) -> [Bytes; 2] {
Expand All @@ -111,11 +111,11 @@ impl WireEncodeVec<2> for UdpDatagram {
}
}

impl<T: Buf> WireDecode<T> for UdpDatagram {
impl<T: Buf> WireDecode<T> for UdpMessage {
type Error = UdpDecodeError;

fn decode(data: &mut T) -> Result<Self, Self::Error> {
if data.remaining() < UdpDatagram::HEADER_LEN {
if data.remaining() < UdpMessage::HEADER_LEN {
return Err(Self::Error::DatagramEmptyOrTruncated);
}

Expand Down Expand Up @@ -161,7 +161,7 @@ mod tests {
destination: MaybeEncoded::Decoded(Ipv4Addr::from_str("10.0.0.2")?.into()),
},
};
let mut datagram = UdpDatagram::new(
let mut datagram = UdpMessage::new(
ByEndpoint {
source: 10001,
destination: 10002,
Expand Down Expand Up @@ -193,7 +193,7 @@ mod tests {
let mut encoded_bytes = BytesMut::new();
encoded_bytes.put(encoded_datagram[0].clone());
encoded_bytes.put(encoded_datagram[1].clone());
assert_eq!(UdpDatagram::decode(&mut encoded_bytes.freeze())?, datagram);
assert_eq!(UdpMessage::decode(&mut encoded_bytes.freeze())?, datagram);

Ok(())
}
Expand Down
14 changes: 7 additions & 7 deletions crates/scion-proto/src/packet/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bytes::Bytes;
use super::{InadequateBufferSize, ScionHeaders, ScionPacketRaw};
use crate::{
address::SocketAddr,
datagram::{UdpDatagram, UdpDecodeError},
datagram::{UdpDecodeError, UdpMessage},
packet::{ByEndpoint, EncodeError},
path::Path,
wire_encoding::{WireDecode, WireEncodeVec},
Expand All @@ -16,7 +16,7 @@ pub struct ScionPacketUdp {
/// Packet headers
pub headers: ScionHeaders,
/// The contained UDP datagram
pub datagram: UdpDatagram,
pub datagram: UdpMessage,
}

impl ScionPacketUdp {
Expand Down Expand Up @@ -62,11 +62,11 @@ impl ScionPacketUdp {
let headers = ScionHeaders::new(
endhosts,
path,
UdpDatagram::PROTOCOL_NUMBER,
payload.len() + UdpDatagram::HEADER_LEN,
UdpMessage::PROTOCOL_NUMBER,
payload.len() + UdpMessage::HEADER_LEN,
)?;
let mut datagram =
UdpDatagram::new(endhosts.map(|e| e.port()), payload).map_err(|_| todo!())?;
UdpMessage::new(endhosts.map(|e| e.port()), payload).map_err(|_| todo!())?;
datagram.set_checksum(&headers.address);

Ok(Self { headers, datagram })
Expand All @@ -77,14 +77,14 @@ impl TryFrom<ScionPacketRaw> for ScionPacketUdp {
type Error = UdpDecodeError;

fn try_from(mut value: ScionPacketRaw) -> Result<Self, Self::Error> {
if value.headers.common.next_header != UdpDatagram::PROTOCOL_NUMBER {
if value.headers.common.next_header != UdpMessage::PROTOCOL_NUMBER {
return Err(UdpDecodeError::WrongProtocolNumber(
value.headers.common.next_header,
));
}
Ok(Self {
headers: value.headers,
datagram: UdpDatagram::decode(&mut value.payload)?,
datagram: UdpMessage::decode(&mut value.payload)?,
})
}
}
Expand Down
27 changes: 25 additions & 2 deletions crates/scion-proto/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! This module contains types for SCION paths and metadata as well as encoding and decoding
//! functions.

use std::net::SocketAddr;
use std::{net::SocketAddr, ops::Deref};

use bytes::Bytes;
use scion_grpc::daemon::v1 as daemon_grpc;
Expand All @@ -27,7 +27,7 @@ pub mod epic;
pub use epic::EpicAuths;

/// A SCION end-to-end path with optional metadata.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub struct Path<T = Bytes> {
/// The raw bytes to be added as the path header to SCION dataplane packets.
pub dataplane_path: DataplanePath<T>,
Expand Down Expand Up @@ -125,6 +125,29 @@ impl Path<Bytes> {
}
}

impl From<Path<&mut [u8]>> for Path<Bytes> {
fn from(value: Path<&mut [u8]>) -> Self {
Self {
dataplane_path: value.dataplane_path.into(),
underlay_next_hop: value.underlay_next_hop,
isd_asn: value.isd_asn,
metadata: value.metadata,
}
}
}

impl<T> PartialEq for Path<T>
where
T: Deref<Target = [u8]>,
{
fn eq(&self, other: &Self) -> bool {
self.dataplane_path == other.dataplane_path
&& self.underlay_next_hop == other.underlay_next_hop
&& self.isd_asn == other.isd_asn
&& self.metadata == other.metadata
}
}
mlegner marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr};
Expand Down
39 changes: 37 additions & 2 deletions crates/scion-proto/src/path/dataplane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl From<u8> for PathType {
pub struct UnsupportedPathType(pub u8);

/// Dataplane path found in a SCION packet.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub enum DataplanePath<T = Bytes> {
/// The empty path type, used for intra-AS hops.
EmptyPath,
Expand Down Expand Up @@ -131,6 +131,17 @@ where
}
}

/// Reverse the path to the provided slice.
///
/// Unsupported path types are copied to the slice, as is.
pub fn reverse_to_slice<'b>(&self, buffer: &'b mut [u8]) -> DataplanePath<&'b mut [u8]> {
match self {
DataplanePath::EmptyPath => DataplanePath::EmptyPath,
DataplanePath::Standard(path) => DataplanePath::Standard(path.reverse_to_slice(buffer)),
DataplanePath::Unsupported { .. } => self.copy_to_slice(buffer),
}
}

/// Reverses the path.
pub fn to_reversed(&self) -> Result<DataplanePath, UnsupportedPathType> {
match self {
Expand Down Expand Up @@ -188,6 +199,30 @@ impl From<StandardPath> for DataplanePath {
}
}

impl<T, U> PartialEq<DataplanePath<U>> for DataplanePath<T>
where
T: Deref<Target = [u8]>,
U: Deref<Target = [u8]>,
{
fn eq(&self, other: &DataplanePath<U>) -> bool {
match (self, other) {
(Self::Standard(lhs), DataplanePath::Standard(rhs)) => lhs.raw() == rhs.raw(),
(
Self::Unsupported {
path_type: l_path_type,
bytes: l_bytes,
},
DataplanePath::Unsupported {
path_type: r_path_type,
bytes: r_bytes,
},
) => l_path_type == r_path_type && l_bytes.deref() == r_bytes.deref(),
(Self::EmptyPath, DataplanePath::EmptyPath) => true,
_ => false,
}
}
}

impl WireEncode for DataplanePath {
type Error = InadequateBufferSize;

Expand Down Expand Up @@ -275,7 +310,7 @@ mod tests {

#[test]
fn reverse_empty() {
let dataplane_path = DataplanePath::EmptyPath;
let dataplane_path = DataplanePath::<Bytes>::EmptyPath;
let reverse_path = dataplane_path.to_reversed().unwrap();
assert_eq!(dataplane_path, reverse_path);
assert_eq!(reverse_path.to_reversed().unwrap(), dataplane_path);
Expand Down
4 changes: 2 additions & 2 deletions crates/scion-proto/src/reliable/registration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use bytes::{Buf, BufMut};
use super::wire_utils::LAYER4_PORT_OCTETS;
use crate::{
address::{HostType, IsdAsn, ServiceAddr, SocketAddr as ScionSocketAddr},
datagram::UdpDatagram,
datagram::UdpMessage,
reliable::{
wire_utils::{encoded_address_and_port_length, encoded_address_length},
ADDRESS_TYPE_OCTETS,
Expand Down Expand Up @@ -85,7 +85,7 @@ impl RegistrationRequest {

self.encode_command_flag(buffer);

buffer.put_u8(UdpDatagram::PROTOCOL_NUMBER);
buffer.put_u8(UdpMessage::PROTOCOL_NUMBER);
buffer.put_u64(self.isd_asn.as_u64());

encode_address(buffer, &self.public_address);
Expand Down
1 change: 1 addition & 0 deletions crates/scion/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license = "Apache-2.0"
publish = false

[dependencies]
async-trait = "0.1.74"
bytes = "1.5.0"
chrono = { workspace = true, features = ["clock"] }
scion-grpc = { version = "0.1.0", path = "../scion-grpc" }
Expand Down
1 change: 1 addition & 0 deletions crates/scion/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

pub mod daemon;
pub mod dispatcher;
pub mod pan;
pub mod udp_socket;
9 changes: 9 additions & 0 deletions crates/scion/src/pan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Path aware networking socket and services.
mod datagram;
pub use datagram::{AsyncScionDatagram, PathAwareDatagram};

mod path_service;
pub use path_service::AsyncPathService;

mod error;
pub use error::{PathErrorKind, ReceiveError, SendError};
Loading