#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Serialize, Deserialize)]
pub struct DeviceAddress
{
domain: u16,
bus: u8,
deviceIdentifier: u8,
function: u4,
}
impl DeviceName for DeviceAddress
{
#[inline]
fn to_string(&self) -> String
{
format!("{:04x}:{:02x}:{:02x}.{:01x}", self.domain, self.bus, self.deviceIdentifier, self.function)
}
}
impl DeviceAddress
{
const DefaultDomain: u16 = 0x0000;
const DefaultBus: u8 = 0x00;
pub fn fromString(value: &str) -> Result<DeviceAddress, DeviceAddressStringParseError>
{
let mut matchCount = 0;
let length = value.len();
if length != NumberOfBytesInPciAddressString
{
return Err(DeviceAddressStringParseError::LengthIsWrong(length));
}
let mut split = value.split(|character|
{
match matchCount
{
0 | 1 =>
{
matchCount += 1;
character == ':'
},
2 =>
{
matchCount += 1;
character == '.'
},
_ => false,
}
});
let domain = match split.next()
{
None => return Err(DeviceAddressStringParseError::NoDomain),
Some(value) =>
{
match u16::from_str_radix(value, 16)
{
Err(cause) => return Err(DeviceAddressStringParseError::CouldNotParseDomain(value.to_owned(), cause)),
Ok(value) => value,
}
}
};
let bus = match split.next()
{
None => return Err(DeviceAddressStringParseError::NoBus),
Some(value) =>
{
match u8::from_str_radix(value, 16)
{
Err(cause) => return Err(DeviceAddressStringParseError::CouldNotParseBus(value.to_owned(), cause)),
Ok(value) => value,
}
}
};
let deviceIdentifier = match split.next()
{
None => return Err(DeviceAddressStringParseError::NoDeviceIdentifier),
Some(value) =>
{
match u8::from_str_radix(value, 16)
{
Err(cause) => return Err(DeviceAddressStringParseError::CouldNotParseDeviceIdentifier(value.to_owned(), cause)),
Ok(value) => value,
}
}
};
let function = match split.next()
{
None => return Err(DeviceAddressStringParseError::NoFunction),
Some(value) =>
{
match u8::from_str_radix(value, 16)
{
Err(cause) => return Err(DeviceAddressStringParseError::CouldNotParseFunction(value.to_owned(), cause)),
Ok(value) => if value > 15
{
return Err(DeviceAddressStringParseError::FunctionExceeds4BitValue(value))
}
else
{
value
},
}
}
};
Ok(DeviceAddress::fromDomainBusDeviceIdAndFunction(domain, bus, deviceIdentifier, function))
}
#[inline(always)]
pub fn fromBusDeviceIdAndFunctionAssumingDefaultDomainAndDefaultBus(deviceIdentifier: u8, function: u4) -> Self
{
Self::fromDomainBusDeviceIdAndFunction(Self::DefaultDomain, Self::DefaultBus, deviceIdentifier, function)
}
#[inline(always)]
pub fn fromBusDeviceIdAndFunctionAssumingDefaultDomain(bus: u8, deviceIdentifier: u8, function: u4) -> Self
{
Self::fromDomainBusDeviceIdAndFunction(Self::DefaultDomain, bus, deviceIdentifier, function)
}
#[inline(always)]
pub fn fromDomainBusDeviceIdAndFunction(domain: u16, bus: u8, deviceIdentifier: u8, function: u4) -> Self
{
debug_assert!(function < 16, "function must be between 0 to 15 inclusive (it's 4-bit) and not be '{}'", function);
DeviceAddress
{
domain: domain,
bus: bus,
deviceIdentifier: deviceIdentifier,
function: function,
}
}
#[inline(always)]
pub fn from_rte_pci_addr(value: &rte_pci_addr) -> Self
{
DeviceAddress
{
domain: value.domain,
bus: value.bus,
deviceIdentifier: value.devid,
function: value.function,
}
}
#[inline(always)]
pub fn as_rte_pci_addr(&self) -> rte_pci_addr
{
rte_pci_addr
{
domain: self.domain,
bus: self.bus,
devid: self.deviceIdentifier,
function: self.function,
}
}
#[inline(always)]
pub fn is_rte_pci_addr(&self, other: &rte_pci_addr) -> bool
{
self.domain == other.domain && self.bus == other.bus && self.deviceIdentifier == other.devid && self.function == other.function
}
#[inline(always)]
pub fn underlyingEthernetPort(&self) -> Option<((EthernetPort, rte_eth_dev))>
{
let mut portIdentifier = 0;
while portIdentifier < EthernetPort::MaximumEthernetPortsU8
{
if let Some(ethernetPort) = EthernetPort::new(portIdentifier)
{
let underlying_rte_eth_dev = ethernetPort.underlyingEthernetDevice();
if !underlying_rte_eth_dev.device.is_null()
{
unsafe
{
let pciDevice = *(rust_RTE_DEV_TO_PCI(underlying_rte_eth_dev.device));
if self.is_rte_pci_addr(&pciDevice.addr)
{
return Some((ethernetPort, underlying_rte_eth_dev));
}
}
}
}
portIdentifier += 1;
}
None
}
#[inline]
pub fn asCString(&self) -> CString
{
CString::new(self.to_string()).unwrap()
}
#[inline(always)]
pub fn probe(&self) -> Result<(), i32>
{
let dpdkAddress = self.as_rte_pci_addr();
let result = unsafe { ::dpdk_sys::rte_eal_pci_probe_one(&dpdkAddress) };
if likely(result == 0)
{
Ok(())
}
else
{
match result
{
negative if negative < 0 => Err(result),
illegal @ _ => panic!("rte_eal_pci_probe_one() returned illegal result '{}'", illegal),
}
}
}
#[inline(always)]
pub fn detach(&self) -> Result<(), i32>
{
let dpdkAddress = self.as_rte_pci_addr();
let result = unsafe { ::dpdk_sys::rte_eal_pci_detach(&dpdkAddress) };
if likely(result == 0)
{
Ok(())
}
else
{
match result
{
negative if negative < 0 => Err(result),
illegal @ _ => panic!("rte_eal_pci_detach() returned illegal result '{}'", illegal),
}
}
}
}