use bytes::Bytes;
pub(crate) const DESCRIPTOR_VERSION: u8 = 1;
pub(crate) const HEADER_LEN: usize = 1 + 1 + 1 + 8 + 8 + 8 + 2;
pub(crate) const MAX_KEY_LEN: usize = 4096;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum DescriptorBackend {
Ucx,
}
impl DescriptorBackend {
pub(crate) fn to_wire(self) -> u8 {
match self {
Self::Ucx => 1,
}
}
pub(crate) fn from_wire(value: u8) -> Option<Self> {
match value {
1 => Some(Self::Ucx),
_ => None,
}
}
pub(crate) fn key(self) -> &'static str {
match self {
Self::Ucx => "ucx",
}
}
pub(crate) fn from_key(key: &str) -> Option<Self> {
match key {
"ucx" => Some(Self::Ucx),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct RdmaDescriptor {
pub backend: DescriptorBackend,
pub generation: u64,
pub addr: u64,
pub len: u64,
pub packed_key: Bytes,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
pub(crate) enum DescriptorError {
#[error("rdma descriptor shorter than its header")]
Truncated,
#[error("unknown rdma descriptor backend: {0}")]
UnknownBackend(u8),
#[error("unknown rdma descriptor version: {0}")]
UnknownVersion(u8),
#[error("unknown rdma descriptor flags: {0:#x}")]
UnknownFlags(u8),
#[error("rdma descriptor names a zero-length range")]
EmptyRange,
#[error("rdma descriptor key length {declared} does not match its {actual} remaining bytes")]
KeyLength {
declared: usize,
actual: usize,
},
}
impl RdmaDescriptor {
pub(crate) fn encode(&self) -> Option<Vec<u8>> {
if self.len == 0 || self.packed_key.is_empty() || self.packed_key.len() > MAX_KEY_LEN {
return None;
}
let key_len = u16::try_from(self.packed_key.len()).ok()?;
let mut out = Vec::with_capacity(HEADER_LEN + self.packed_key.len());
out.push(self.backend.to_wire());
out.push(DESCRIPTOR_VERSION);
out.push(0); out.extend_from_slice(&self.generation.to_le_bytes());
out.extend_from_slice(&self.addr.to_le_bytes());
out.extend_from_slice(&self.len.to_le_bytes());
out.extend_from_slice(&key_len.to_le_bytes());
out.extend_from_slice(&self.packed_key);
Some(out)
}
pub(crate) fn decode(bytes: &[u8]) -> Result<Self, DescriptorError> {
let header: &[u8; HEADER_LEN] = bytes
.get(..HEADER_LEN)
.and_then(|h| h.try_into().ok())
.ok_or(DescriptorError::Truncated)?;
let backend = DescriptorBackend::from_wire(header[0])
.ok_or(DescriptorError::UnknownBackend(header[0]))?;
if header[1] != DESCRIPTOR_VERSION {
return Err(DescriptorError::UnknownVersion(header[1]));
}
if header[2] != 0 {
return Err(DescriptorError::UnknownFlags(header[2]));
}
let generation = u64::from_le_bytes(header[3..11].try_into().expect("8 bytes"));
let addr = u64::from_le_bytes(header[11..19].try_into().expect("8 bytes"));
let len = u64::from_le_bytes(header[19..27].try_into().expect("8 bytes"));
if len == 0 {
return Err(DescriptorError::EmptyRange);
}
let declared = u16::from_le_bytes(header[27..29].try_into().expect("2 bytes")) as usize;
let actual = bytes.len() - HEADER_LEN;
if declared == 0 || declared > MAX_KEY_LEN || declared != actual {
return Err(DescriptorError::KeyLength { declared, actual });
}
Ok(Self {
backend,
generation,
addr,
len,
packed_key: Bytes::copy_from_slice(&bytes[HEADER_LEN..]),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample() -> RdmaDescriptor {
RdmaDescriptor {
backend: DescriptorBackend::Ucx,
generation: 0xDEAD_BEEF_1234_5678,
addr: 0x7F00_0000_1000,
len: 64 * 1024,
packed_key: Bytes::from_static(&[1, 2, 3, 4, 5, 6, 7, 8, 9]),
}
}
#[test]
fn roundtrip_is_exact() {
let d = sample();
let bytes = d.encode().expect("encode");
assert_eq!(bytes.len(), HEADER_LEN + 9);
assert_eq!(RdmaDescriptor::decode(&bytes).expect("decode"), d);
}
#[test]
fn layout_is_the_documented_one() {
let bytes = sample().encode().expect("encode");
assert_eq!(bytes[0], 1, "backend discriminator");
assert_eq!(bytes[1], DESCRIPTOR_VERSION);
assert_eq!(bytes[2], 0, "flags");
assert_eq!(&bytes[3..11], &0xDEAD_BEEF_1234_5678u64.to_le_bytes());
assert_eq!(&bytes[11..19], &0x7F00_0000_1000u64.to_le_bytes());
assert_eq!(&bytes[19..27], &(64u64 * 1024).to_le_bytes());
assert_eq!(&bytes[27..29], &9u16.to_le_bytes());
}
#[test]
fn truncation_anywhere_is_refused() {
let bytes = sample().encode().expect("encode");
for cut in 0..bytes.len() {
let err = RdmaDescriptor::decode(&bytes[..cut])
.expect_err("a truncated descriptor must not decode");
if cut < HEADER_LEN {
assert_eq!(err, DescriptorError::Truncated, "cut at {cut}");
} else {
assert!(
matches!(err, DescriptorError::KeyLength { .. }),
"cut at {cut}: {err}"
);
}
}
}
#[test]
fn trailing_bytes_are_refused() {
let mut bytes = sample().encode().expect("encode");
bytes.push(0);
assert_eq!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::KeyLength {
declared: 9,
actual: 10
})
);
}
#[test]
fn a_lying_key_length_is_refused() {
let mut bytes = sample().encode().expect("encode");
bytes[27..29].copy_from_slice(&300u16.to_le_bytes());
assert!(matches!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::KeyLength {
declared: 300,
actual: 9
})
));
bytes[27..29].copy_from_slice(&4u16.to_le_bytes());
assert!(matches!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::KeyLength { declared: 4, .. })
));
}
#[test]
fn unknown_backend_version_and_flags_are_refused() {
let good = sample().encode().expect("encode");
let mut bytes = good.clone();
bytes[0] = 7;
assert_eq!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::UnknownBackend(7))
);
let mut bytes = good.clone();
bytes[1] = 2;
assert_eq!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::UnknownVersion(2))
);
let mut bytes = good;
bytes[2] = 0b10;
assert_eq!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::UnknownFlags(0b10))
);
}
#[test]
fn a_zero_length_range_is_refused_both_ways() {
let mut d = sample();
d.len = 0;
assert!(d.encode().is_none(), "encode must not emit what it refuses");
let mut bytes = sample().encode().expect("encode");
bytes[19..27].copy_from_slice(&0u64.to_le_bytes());
assert_eq!(
RdmaDescriptor::decode(&bytes),
Err(DescriptorError::EmptyRange)
);
}
#[test]
fn an_empty_or_oversized_key_never_encodes() {
let mut d = sample();
d.packed_key = Bytes::new();
assert!(d.encode().is_none());
let mut d = sample();
d.packed_key = Bytes::from(vec![0u8; MAX_KEY_LEN + 1]);
assert!(d.encode().is_none());
}
#[test]
fn backend_names_and_wire_values_agree() {
assert_eq!(
DescriptorBackend::from_key("ucx"),
Some(DescriptorBackend::Ucx)
);
assert_eq!(DescriptorBackend::from_key("nixl"), None);
assert_eq!(
DescriptorBackend::from_wire(DescriptorBackend::Ucx.to_wire()),
Some(DescriptorBackend::Ucx)
);
assert_eq!(DescriptorBackend::Ucx.key(), "ucx");
}
}