diff --git a/io-engine/src/bdev/dev.rs b/io-engine/src/bdev/dev.rs index 727a9e0a3..c8f87909d 100644 --- a/io-engine/src/bdev/dev.rs +++ b/io-engine/src/bdev/dev.rs @@ -66,7 +66,12 @@ pub(crate) mod uri { } "malloc" => Ok(Box::new(malloc::Malloc::try_from(&url)?)), "null" => Ok(Box::new(null_bdev::Null::try_from(&url)?)), - "nvmf" => Ok(Box::new(nvmx::NvmfDeviceTemplate::try_from(&url)?)), + // keeping nvmf scheme so existing tests(if any, setting this + // scheme) work. The replicas and nexus however should + // always be exposing nvmf+tcp or nvmf+rdma now. + "nvmf" | "nvmf+tcp" | "nvmf+rdma+tcp" => { + Ok(Box::new(nvmx::NvmfDeviceTemplate::try_from(&url)?)) + } "pcie" => Ok(Box::new(nvme::NVMe::try_from(&url)?)), "uring" => Ok(Box::new(uring::Uring::try_from(&url)?)), "nexus" => Ok(Box::new(nx::Nexus::try_from(&url)?)), diff --git a/io-engine/src/bdev_api.rs b/io-engine/src/bdev_api.rs index cfbcc05e8..9c39d892c 100644 --- a/io-engine/src/bdev_api.rs +++ b/io-engine/src/bdev_api.rs @@ -126,7 +126,7 @@ where Ok(device) if device.get_name() == bdev.name() => { bdev.driver() == match uri.scheme() { - "nvmf" | "pcie" => "nvme", + "nvmf" | "nvmf+tcp" | "nvmf+rdma+tcp" | "pcie" => "nvme", scheme => scheme, } } @@ -143,7 +143,7 @@ where Ok(device) if device.get_name() == bdev.name() => { bdev.driver() == match uri.scheme() { - "nvmf" | "pcie" => "nvme", + "nvmf" | "nvmf+tcp" | "nvmf+rdma+tcp" | "pcie" => "nvme", scheme => scheme, } } diff --git a/io-engine/src/core/bdev.rs b/io-engine/src/core/bdev.rs index 19e4a8abd..8d2814076 100644 --- a/io-engine/src/core/bdev.rs +++ b/io-engine/src/core/bdev.rs @@ -203,7 +203,7 @@ where type Error = CoreError; type Output = String; - /// share the bdev over NVMe-OF TCP + /// share the bdev over NVMe-OF TCP(and RDMA if enabled) async fn share_nvmf( self: Pin<&mut Self>, props: Option, diff --git a/io-engine/src/subsys/nvmf/transport.rs b/io-engine/src/subsys/nvmf/transport.rs index 56e47e05b..1f3be04bd 100644 --- a/io-engine/src/subsys/nvmf/transport.rs +++ b/io-engine/src/subsys/nvmf/transport.rs @@ -154,9 +154,18 @@ impl TransportId { impl Display for TransportId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + // If an rdma transport is found in transport id, we modify the + // trstring for uri scheme to explicitly indicate the tcp support + // also by default when there is rdma available. + let trstring = match self.0.trstring.as_str() { + "RDMA" => "rdma+tcp".to_string(), + _else => _else.to_lowercase(), + }; + write!( f, - "nvmf://{}:{}", + "nvmf+{}://{}:{}", + trstring, self.0.traddr.as_str(), self.0.trsvcid.as_str() ) diff --git a/io-engine/src/target/nvmf.rs b/io-engine/src/target/nvmf.rs index c92c0331c..f247d821a 100644 --- a/io-engine/src/target/nvmf.rs +++ b/io-engine/src/target/nvmf.rs @@ -35,9 +35,16 @@ pub async fn unshare(uuid: &str) -> Result<(), NvmfError> { pub fn get_uri(uuid: &str) -> Option { if let Some(ss) = NvmfSubsystem::nqn_lookup(uuid) { - // for now we only pop the first but we can share a bdev - // over multiple nqn's - ss.uri_endpoints().unwrap().pop() + // If there is rdma capable uri available, return that. Otherwise, + // for now we only pop the most relevant, but we can share a bdev + // over multiple nqn's. + let mut uris = ss.uri_endpoints().expect("no uri endpoints"); + let rdma_uri = uris + .iter() + .find(|u| u.starts_with("nvmf+rdma+tcp")) + .cloned(); + + rdma_uri.or(uris.pop()) } else { None } diff --git a/libnvme-rs/src/nvme_uri.rs b/libnvme-rs/src/nvme_uri.rs index 328b0e74d..7298011dc 100644 --- a/libnvme-rs/src/nvme_uri.rs +++ b/libnvme-rs/src/nvme_uri.rs @@ -42,12 +42,14 @@ impl Drop for NvmeStringWrapper { #[derive(Debug, PartialEq)] enum NvmeTransportType { Tcp, + Rdma, } impl NvmeTransportType { fn to_str(&self) -> &str { match self { NvmeTransportType::Tcp => "tcp", + NvmeTransportType::Rdma => "rdma", } } } @@ -83,6 +85,7 @@ impl TryFrom<&str> for NvmeTarget { let trtype = match url.scheme() { "nvmf" | "nvmf+tcp" => Ok(NvmeTransportType::Tcp), + "nvmf+rdma+tcp" => Ok(NvmeTransportType::Rdma), _ => Err(NvmeError::UrlError { source: ParseError::IdnaError, }),