#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub(crate) struct ethtool_rxfh
{
pub(crate) cmd: u32,
pub(crate) rss_context: Option<ContextIdentifier>,
pub(crate) indir_size: u32,
pub(crate) key_size: u32,
pub(crate) hfunc: u8,
rsvd8: [u8; 3],
rsvd32: u32,
pub(crate) rss_config: __IncompleteArrayField<u8>,
}
impl EthtoolCommand for ethtool_rxfh
{
#[inline(always)]
fn command(&self) -> u32
{
self.cmd
}
}
impl VariablySizedEthtoolCommand for ethtool_rxfh
{
type ArrayElement = u8;
#[inline(always)]
fn array_length(&self) -> u32
{
let size_in_bytes = self.indirection_table_size_in_bytes() + self.key_size();
size_in_bytes as u32
}
}
impl VariablySizedEthtoolCommandWrapper<ethtool_rxfh>
{
#[inline(always)]
pub(crate) fn configured_hash_settings(&self) -> Result<HashFunctionConfiguration, HashFunctionNameUnsupportedError>
{
Ok
(
HashFunctionConfiguration
{
function: self.hash_function()?,
indirection_table: self.hash_indirection_table().map(|slice| IndirectionTable(slice.to_vec())),
seed: self.hash_key_bytes().map(|slice| HashFunctionSeed(slice.to_vec())),
}
)
}
#[inline(always)]
fn hash_function(&self) -> Result<Option<ETH_RSS_HASH>, HashFunctionNameUnsupportedError>
{
let hash_function_bit_mask = self.hfunc;
if hash_function_bit_mask == 0
{
Ok(None)
}
else
{
let bit = self.hfunc.trailing_zeros();
if (bit as usize) > ETH_RSS_HASH::COUNT
{
Err(HashFunctionNameUnsupportedError)
}
else
{
Ok(Some(unsafe { transmute(bit as u8) }))
}
}
}
#[inline(always)]
fn hash_indirection_table(&self) -> Option<&[QueueIdentifier]>
{
let length = self.indir_size();
if length == 0
{
None
}
else
{
Some(unsafe { from_raw_parts(self.array_start() as *const QueueIdentifier, self.indir_size() ) })
}
}
#[inline(always)]
fn hash_key_bytes(&self) -> Option<&[u8]>
{
let length = self.key_size();
if length == 0
{
None
}
else
{
Some(unsafe { from_raw_parts(self.array_start().add(self.indirection_table_size_in_bytes()), length) })
}
}
}
impl ethtool_rxfh
{
pub(crate) fn get_indirection_table_size_and_key_size(context_identifier: Option<ContextIdentifier>) -> Self
{
Self::get_indirection_table_and_key_data(context_identifier, 0, 0)
}
pub(crate) fn reset(context_identifier: Option<ContextIdentifier>) -> Self
{
Self::set_indirection_table_and_key_data(context_identifier, None, 0, 0)
}
#[inline(always)]
pub(crate) fn get_indirection_table_and_key(context_identifier: Option<ContextIdentifier>, indirection_size: usize, key_size: usize) -> VariablySizedEthtoolCommandWrapper<Self>
{
Self::new_with_initialized_header_but_uninitialized_array(ethtool_rxfh::get_indirection_table_and_key_data(context_identifier, indirection_size, key_size))
}
pub(crate) fn set(context_identifier_or_create: Option<ContextIdentifier>, configured_hash_settings: &HashFunctionConfiguration) -> VariablySizedEthtoolCommandWrapper<Self>
{
let indirection_table = configured_hash_settings.indirection_table.as_ref();
let indirection_size = indirection_table.map(|vec| vec.len()).unwrap_or(0);
let key = configured_hash_settings.seed.as_ref();
let key_size = key.map(|vec| vec.len()).unwrap_or(0);
let mut this = Self::new_with_initialized_header_but_uninitialized_array(Self::set_indirection_table_and_key_data(context_identifier_or_create, configured_hash_settings.function, indirection_size, key_size));
let array_start = this.array_start_mut();
let array_start = array_start as *mut QueueIdentifier;
let indirection_table_end = if let Some(indirection_table) = indirection_table
{
unsafe
{
array_start.copy_from_nonoverlapping(indirection_table.as_ptr(), indirection_size);
array_start.add(indirection_size)
}
}
else
{
array_start
};
if let Some(key) = key
{
let key_start = indirection_table_end as *mut u8;
unsafe { key_start.copy_from_nonoverlapping(key.as_ptr(), key_size) }
}
this
}
fn get_indirection_table_and_key_data(context_identifier: Option<ContextIdentifier>, indirection_size: usize, key_size: usize) -> Self
{
Self
{
cmd: ETHTOOL_GRSSH,
rss_context: context_identifier,
indir_size: indirection_size as u32,
key_size: key_size as u32,
hfunc: 0,
rsvd8: [0; 3],
rsvd32: 0,
rss_config: __IncompleteArrayField::Default,
}
}
fn set_indirection_table_and_key_data(context_identifier_or_create: Option<ContextIdentifier>, hash_function: Option<ETH_RSS_HASH>, indirection_size: usize, key_size: usize) -> Self
{
Self
{
cmd: ETHTOOL_SRSSH,
rss_context: context_identifier_or_create,
indir_size: indirection_size as u32,
key_size: key_size as u32,
hfunc: match hash_function
{
None => 0,
Some(hash_function) => (1 << (hash_function as u8)),
},
rsvd8: [0; 3],
rsvd32: 0,
rss_config: __IncompleteArrayField::Default,
}
}
fn indirection_table_size_in_bytes(&self) -> usize
{
const ElementSize: usize = size_of::<QueueIdentifier>();
self.indir_size() * ElementSize
}
#[inline(always)]
fn indir_size(&self) -> usize
{
self.indir_size as usize
}
#[inline(always)]
fn key_size(&self) -> usize
{
self.key_size as usize
}
}