#[allow(missing_debug_implementations)]
pub struct EthernetPortConfiguration
{
pub receiveQueueConfigurations: ArrayVec<[ReceiveQueueConfiguration; MaximumReceiveQueues]>,
pub transmitQueueConfigurations: ArrayVec<[TransmitQueueConfiguration; MaximumTransmitQueues]>,
pub linkSpeeds: LinkSpeeds,
pub receiveModeConfiguration: EthernetPortReceiveModeConfiguration,
pub transmitModeConfiguration: EthernetPortTransmitModeConfiguration,
pub loopBackOperationMode: u32,
pub receiveSideScalingHashFunctionConfiguration: ReceiveSideScalingHashFunctionConfiguration,
pub receiveSideScalingHashFilter: Option<HashFilter>,
pub receiveSideScalingRetaIndirectionTable: Option<ReceiveSideScalingRetaIndirectionTable>,
pub receiveVmdQDataCentreBridgingConfiguration: ReceiveVmdQDataCentreBridgingConfiguration,
pub receiveDataCentreBridgingConfiguration: ReceiveDataCentreBridgingConfiguration,
pub receiveVmdQConfiguration: ReceiveVmdQConfiguration,
pub transmitAdvancedConfiguration: TransmitAdvancedConfiguration,
pub dataCentreBridgingCapability: DataCentreBridgingCapability,
pub flowDirectorConfiguration: FlowDirectorConfiguration,
pub enableDeviceIscInterrupts: bool,
pub deviceInterruptReceiveQueue: QueueIdentifier,
pub flowControl: Option<FlowControl>,
pub dataCentreBridgingPriorityFlowControl: Option<DataCentreBridgingPriorityFlowControl>,
pub isPromiscuous: bool,
pub enableAllMulticastReceive: bool,
pub maximumTransmissionUnitSizeInBytes: MaximumTransmissionUnitSizeInBytes,
pub multicastMediaAccessControlAddressesToFilter: HashSet<MediaAccessControlAddress>,
pub udpTunnelsToOffload: HashSet<UdpTunnelConfiguration>,
pub enableTimestamping: bool,
pub linkIsUp: bool,
pub ledIsLit: bool,
pub defaultMediaAccessControlAddress: Option<MediaAccessControlAddress>,
pub additionalMediaAccessControlAddresses: HashSet<(MediaAccessControlAddress, Option<u6>)>,
pub trafficMirroringRules: HashMap<TrafficMirroringRuleNumber, TrafficMirroringRule>,
pub virtualLanOffloadFeatures: Option<VirtualLanOffloadFeatures>,
}
impl EthernetPortConfiguration
{
pub fn restrictNumberOfQueuePairsToMaximum(&mut self, maximumNumberOfReceiveThenTransmitQueuePairs: u16)
{
let maximumNumberOfReceiveThenTransmitQueuePairs = maximumNumberOfReceiveThenTransmitQueuePairs as usize;
let borrowReceive = &mut self.receiveQueueConfigurations;
while borrowReceive.len() > maximumNumberOfReceiveThenTransmitQueuePairs
{
borrowReceive.pop();
}
let borrowTransmit = &mut self.transmitQueueConfigurations;
while borrowTransmit.len() > maximumNumberOfReceiveThenTransmitQueuePairs
{
borrowTransmit.pop();
}
}
pub fn configureAndStartWithQueues<Q: QueueMemoryConfiguration>(&mut self, ethernetPortInformation: &EthernetPortInformation, queueMemoryConfiguration: &Q) -> EthernetPortConfigurationResult
{
debug_assert!(self.receiveQueueConfigurations.len() > 0, "receiveQueueConfigurations.len() can not be zero");
debug_assert!(self.transmitQueueConfigurations.len() > 0, "transmitQueueConfigurations.len() can not be zero");
let numberOfReceiveQueues = self.receiveQueueConfigurations.len();
let numberOfTransmitQueues = self.transmitQueueConfigurations.len();
self.configure(ethernetPortInformation.portIdentifier(), numberOfReceiveQueues as u16, numberOfTransmitQueues as u16).expect("Could not configure ethernet port; check PMD_INIT_LOG, level INFO or NOTICE");
let mut failures = EthernetPortConfigurationFailures::new();
let mut receiveQueues = ArrayVec::<[ReceiveQueue; MaximumReceiveQueues]>::new();
for queueIdentifier in 0..numberOfReceiveQueues
{
let receiveQueueConfiguration = self.receiveQueueConfigurations.get(queueIdentifier).unwrap();
let queueIdentifier = queueIdentifier as QueueIdentifier;
if let Some(receiveQueue) = ReceiveQueue::new(ethernetPortInformation, queueIdentifier, queueMemoryConfiguration, &receiveQueueConfiguration, &mut failures)
{
receiveQueues.push(receiveQueue);
}
else
{
failures.push(EthernetPortConfigurationFailureKind::CouldNotCreateReceiveQueueBecauseOutOfMemory(queueIdentifier))
}
}
let ethernetPort = ethernetPortInformation.ethernetPort();
let mut transmitQueues = ArrayVec::<[TransmitQueue; MaximumTransmitQueues]>::new();
for queueIdentifier in 0..numberOfTransmitQueues
{
let transmitQueueConfiguration = self.transmitQueueConfigurations.get(queueIdentifier).unwrap();
let queueIdentifier = queueIdentifier as QueueIdentifier;
if let Some(transmitQueue) = TransmitQueue::new(ethernetPortInformation, queueIdentifier, queueMemoryConfiguration, &transmitQueueConfiguration, &mut failures)
{
transmitQueues.push(transmitQueue);
}
else
{
failures.push(EthernetPortConfigurationFailureKind::CouldNotCreateTransmitQueueBecauseOutOfMemory(queueIdentifier))
}
}
if let Some(flowControl) = self.flowControl
{
failures.ifError(ethernetPort.setFlowControl(flowControl), EthernetPortConfigurationFailureKind::SetFlowControl);
}
if let Some(dataCentreBridgingPriorityFlowControl) = self.dataCentreBridgingPriorityFlowControl
{
failures.ifError(ethernetPort.setDataCentreBridgingPriorityFlowControl(dataCentreBridgingPriorityFlowControl), EthernetPortConfigurationFailureKind::SetDataCentreBridgingPriorityFlowControl);
}
ethernetPort.start().expect("Could not start EthernetPort");
if let Some(ref receiveSideScalingHashFilter) = self.receiveSideScalingHashFilter
{
failures.ifError(ethernetPort.setHashFilter(receiveSideScalingHashFilter), EthernetPortConfigurationFailureKind::ReceiveSideScalingHashFilter)
}
if let Some(ref mut receiveSideScalingRetaIndirectionTable) = self.receiveSideScalingRetaIndirectionTable
{
failures.ifError(ethernetPort.updateRetaIndirectionTable(receiveSideScalingRetaIndirectionTable), EthernetPortConfigurationFailureKind::UpdateRetaIndirectionTable)
}
if self.isPromiscuous
{
ethernetPort.enablePromiscuousReceive();
}
else
{
ethernetPort.disablePromiscuousReceive();
}
if self.enableAllMulticastReceive
{
ethernetPort.enableAllMulticastReceive();
}
else
{
ethernetPort.disableAllMulticastReceive();
}
failures.ifError(ethernetPort.clearMulticastMediaAccessControlAddressesToFilter(), EthernetPortConfigurationFailureKind::ClearMulticastMediaAccessControlAddressesToFilter);
failures.ifError(ethernetPort.setMulticastMediaAccessControlAddressesToFilter(&self.multicastMediaAccessControlAddressesToFilter), EthernetPortConfigurationFailureKind::SetMulticastMediaAccessControlAddressesToFilter);
failures.ifError(ethernetPort.setMaximumTransmissionUnit(self.maximumTransmissionUnitSizeInBytes.as_u16()), EthernetPortConfigurationFailureKind::SetMaximumTransmissionUnit);
for udpTunnelConfiguration in &self.udpTunnelsToOffload
{
let udpTunnelConfiguration = *udpTunnelConfiguration;
if let Err(error) = ethernetPort.addUdpTunnelOffload(udpTunnelConfiguration)
{
failures.push(EthernetPortConfigurationFailureKind::AddUdpTunnelOffload(error, udpTunnelConfiguration));
}
}
if self.enableTimestamping
{
failures.ifError(ethernetPort.enableTimestamping(), EthernetPortConfigurationFailureKind::EnableTimestamping);
}
else
{
failures.ifError(ethernetPort.disableTimestamping(), EthernetPortConfigurationFailureKind::DisableTimestamping);
}
for receiveQueue in &receiveQueues
{
if receiveQueue.startIfDeferred().is_err()
{
failures.push(EthernetPortConfigurationFailureKind::ReceiveQueueDeferredStart(receiveQueue.queueIdentifier))
}
}
for transmitQueue in &transmitQueues
{
if transmitQueue.startIfDeferred().is_err()
{
failures.push(EthernetPortConfigurationFailureKind::TransmitQueueDeferredStart(transmitQueue.queueIdentifier))
}
}
if self.linkIsUp
{
failures.ifError(ethernetPort.setLinkUp(), EthernetPortConfigurationFailureKind::LinkUp);
}
else
{
failures.ifError(ethernetPort.setLinkDown(), EthernetPortConfigurationFailureKind::LinkDown);
}
if self.ledIsLit
{
failures.ifError(ethernetPort.turnLedOn(), EthernetPortConfigurationFailureKind::LedOn);
}
else
{
failures.ifError(ethernetPort.turnLedOff(), EthernetPortConfigurationFailureKind::LedOff);
}
if let Some(defaultMediaAccessControlAddress) = self.defaultMediaAccessControlAddress
{
failures.ifError(ethernetPort.setDefaultMediaAccessControlAddress(defaultMediaAccessControlAddress), EthernetPortConfigurationFailureKind::SetDefaultMediaAccessControlAddress);
}
for &(additionalMediaAccessControlAddress, vmdqPortIndex) in &self.additionalMediaAccessControlAddresses
{
if let Err(error) = ethernetPort.addMediaAccessControlAddress(additionalMediaAccessControlAddress, vmdqPortIndex)
{
failures.push(EthernetPortConfigurationFailureKind::AddMediaAccessControlAddress(error, (additionalMediaAccessControlAddress, vmdqPortIndex)));
}
}
for (trafficMirroringRuleNumber, trafficMirroringRule) in self.trafficMirroringRules.iter()
{
if let Err(error) = ethernetPort.enableTrafficMirroringRule(*trafficMirroringRuleNumber, trafficMirroringRule)
{
failures.push(EthernetPortConfigurationFailureKind::EnableTrafficMirroringRule(error, *trafficMirroringRuleNumber));
}
}
if let Some(virtualLanOffloadFeatures) = self.virtualLanOffloadFeatures
{
failures.ifError(ethernetPort.setVirtualLanOffloading(virtualLanOffloadFeatures), EthernetPortConfigurationFailureKind::SetVirtualLanOffloadFeatures);
}
(receiveQueues, transmitQueues, failures)
}
#[inline(always)]
fn configure(&self, portIdentifier: EthernetPortIdentifier, numberOfReceiveQueues: u16, numberOfTransmitQueues: u16) -> Result<(), i32>
{
debug_assert!(numberOfReceiveQueues > 0, "numberOfReceiveQueues can not be zero");
debug_assert!(numberOfTransmitQueues > 0, "numberOfTransmitQueues can not be zero");
let mustLiveAtLeastAsLongAs_receiveSideScalingHashFunctionConfiguration = self.receiveSideScalingHashFunctionConfiguration.as_rte_eth_rss_conf();
let ethernetInternalConfiguration = rte_eth_conf
{
link_speeds: self.linkSpeeds.as_uint32_t(),
rxmode: self.receiveModeConfiguration.as_rte_eth_rxmode(),
txmode: self.transmitModeConfiguration.as_rte_eth_txmode(),
lpbk_mode: self.loopBackOperationMode,
rx_adv_conf: rte_eth_conf_AnonymousStruct_rx_adv_conf
{
rss_conf: mustLiveAtLeastAsLongAs_receiveSideScalingHashFunctionConfiguration,
vmdq_dcb_conf: self.receiveVmdQDataCentreBridgingConfiguration.as_rte_eth_vmdq_dcb_conf(),
dcb_rx_conf: self.receiveDataCentreBridgingConfiguration.as_rte_eth_dcb_rx_conf(),
vmdq_rx_conf: self.receiveVmdQConfiguration.as_rte_eth_vmdq_rx_conf(),
},
tx_adv_conf: self.transmitAdvancedConfiguration.as_rte_eth_conf_AnonymousUnion_tx_adv_conf(),
dcb_capability_en: self.dataCentreBridgingCapability.bits(),
fdir_conf: self.flowDirectorConfiguration.as_rte_fdir_conf(),
intr_conf: rte_intr_conf
{
lsc: if self.enableDeviceIscInterrupts
{
1
}
else
{
0
},
rxq: self.deviceInterruptReceiveQueue,
},
};
match unsafe { ::dpdk_sys::rte_eth_dev_configure(portIdentifier, numberOfReceiveQueues, numberOfTransmitQueues, ðernetInternalConfiguration) }
{
0 => Ok(()),
result if result < 0 => Err(result),
unexpected @ _ => panic!("Unexpected positive error result '{}' from rte_eth_dev_configure()", unexpected),
}
}
}