Skip to content

Commit

Permalink
feat: add datagram trait and path-aware datagram (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpcsmith authored Dec 20, 2023
1 parent f45a231 commit d86b042
Show file tree
Hide file tree
Showing 16 changed files with 728 additions and 286 deletions.
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
}
}

#[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

0 comments on commit d86b042

Please sign in to comment.