use std::sync::Arc;
use bytes::Bytes;
use futures::future::BoxFuture;
use velo_ext::InstanceId;
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum RdmaError {
#[error("rdma registration layer is shutting down")]
ShuttingDown,
#[error(
"rdma registered-bytes budget exceeded: {requested} B requested, {registered} B registered, {budget} B budget"
)]
BudgetExceeded {
requested: u64,
registered: u64,
budget: u64,
},
#[error("rdma region not found")]
RegionNotFound,
#[error("rdma range outside the registered region")]
OutOfRange,
#[error("malformed packed remote key")]
InvalidKey,
#[error("rdma backend: {0}")]
Backend(String),
#[error("no rdma backend configured for this instance")]
NotConfigured,
#[error("region owns no buffer")]
NotOwned,
#[error("rdma operation timed out")]
Timeout,
}
#[derive(Debug, Clone)]
pub(crate) struct BackendRegion {
pub backend_region_id: u64,
pub effective_addr: u64,
pub effective_len: u64,
pub packed_key: Bytes,
}
#[derive(Debug, Clone)]
pub(crate) struct BackendGet {
pub peer: InstanceId,
pub remote_addr: u64,
pub packed_key: Bytes,
pub local_region_id: u64,
pub local_offset: u64,
pub len: u64,
}
pub(crate) trait RdmaBackend: Send + Sync {
fn key(&self) -> &str;
fn map(&self, ptr: usize, len: usize) -> BoxFuture<'_, Result<BackendRegion, RdmaError>>;
fn unmap(&self, backend_region_id: u64) -> BoxFuture<'_, Result<(), RdmaError>>;
fn get(&self, req: BackendGet) -> BoxFuture<'_, Result<(), RdmaError>>;
fn live_registrations(&self) -> Option<usize> {
None
}
}
pub(crate) struct UcxBackend {
endpoint: crate::transports::ucx::rma::RdmaEndpoint,
}
impl UcxBackend {
pub(crate) fn new(endpoint: crate::transports::ucx::rma::RdmaEndpoint) -> Arc<Self> {
Arc::new(Self { endpoint })
}
}
impl RdmaBackend for UcxBackend {
fn key(&self) -> &str {
"ucx"
}
fn map(&self, ptr: usize, len: usize) -> BoxFuture<'_, Result<BackendRegion, RdmaError>> {
Box::pin(async move {
let region = self
.endpoint
.map_region(ptr, len)
.await
.map_err(rma_error)?;
Ok(BackendRegion {
backend_region_id: region.region_id,
effective_addr: region.effective_addr,
effective_len: region.effective_len,
packed_key: region.packed_rkey,
})
})
}
fn unmap(&self, backend_region_id: u64) -> BoxFuture<'_, Result<(), RdmaError>> {
Box::pin(async move {
self.endpoint
.unmap_region(backend_region_id)
.await
.map_err(rma_error)
})
}
fn live_registrations(&self) -> Option<usize> {
Some(self.endpoint.live_regions())
}
fn get(&self, req: BackendGet) -> BoxFuture<'_, Result<(), RdmaError>> {
Box::pin(async move {
self.endpoint
.get(crate::transports::ucx::rma::RmaGetRequest {
peer: req.peer,
remote_addr: req.remote_addr,
packed_rkey: req.packed_key,
local_region: req.local_region_id,
local_offset: req.local_offset,
len: req.len,
})
.await
.map_err(rma_error)
})
}
}
fn rma_error(e: crate::transports::ucx::rma::RmaError) -> RdmaError {
use crate::transports::ucx::rma::RmaError as E;
match e {
E::ShuttingDown => RdmaError::ShuttingDown,
E::OutOfRange => RdmaError::OutOfRange,
E::RegionNotFound => RdmaError::RegionNotFound,
E::InvalidRkey => RdmaError::InvalidKey,
other => RdmaError::Backend(format!("ucx: {other}")),
}
}