#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[repr(transparent)]
#[derive(Deserialize, Serialize)]
pub struct FeatureGroup(HashSet<Feature>);
impl Deref for FeatureGroup
{
type Target = HashSet<Feature>;
#[inline(always)]
fn deref(&self) -> &Self::Target
{
&self.0
}
}
impl DerefMut for FeatureGroup
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target
{
&mut self.0
}
}
impl From<HashSet<Feature>> for FeatureGroup
{
#[inline(always)]
fn from(value: HashSet<Feature>) -> Self
{
Self(value)
}
}
impl Into<HashSet<Feature>> for FeatureGroup
{
#[inline(always)]
fn into(self) -> HashSet<Feature>
{
self.0
}
}
impl FeatureGroup
{
#[inline(always)]
pub(crate) fn enable(&self) -> HashMap<Feature, bool>
{
self.0.iter().map(|key| (*key, true)).collect()
}
#[inline(always)]
pub(crate) fn disable(&self) -> HashMap<Feature, bool>
{
self.0.iter().map(|key| (*key, false)).collect()
}
#[inline(always)]
pub fn all() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup =
{
let mut hash_set = HashSet::with_capacity(NETIF_F::NETDEV_FEATURE_COUNT);
for feature in NETIF_F::iter()
{
hash_set.insert(feature);
}
FeatureGroup(hash_set)
};
}
&Static
}
#[inline(always)]
pub fn ethtool_sg() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_SG_BIT,
NETIF_F_FRAGLIST_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_tx() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_IP_CSUM_BIT,
NETIF_F_HW_CSUM_BIT,
NETIF_F_IPV6_CSUM_BIT,
NETIF_F_FCOE_CRC_BIT,
NETIF_F_SCTP_CRC_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_txvlan() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_HW_VLAN_CTAG_TX_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_rxvlan() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_HW_VLAN_CTAG_RX_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_gso() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_GSO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_gro() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_GRO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_lro() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_LRO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_tso() -> &'static Self
{
Self::NETIF_F_ALL_TSO()
}
#[inline(always)]
#[deprecated]
pub fn ethtool_ufo() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_GSO_UDP_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_ntuple() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_NTUPLE_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_rxhash() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_RXHASH_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn ethtool_rx() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_RXCSUM_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn internet_protocols_checksum() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_IP_CSUM_BIT,
NETIF_F_IPV6_CSUM_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn internet_protocols_checksum_in_hardware() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_HW_CSUM_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn generic_send_offload_encapsulation() -> &'static Self
{
Self::NETIF_F_GSO_ENCAP_ALL()
}
#[inline(always)]
pub fn NETIF_F_NEVER_CHANGE() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_VLAN_CHALLENGED_BIT,
NETIF_F_LLTX_BIT,
NETIF_F_NETNS_LOCAL_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_ETHTOOL_BITS() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup =
{
let mut set = HashSet::new();
for feature in FeatureGroup::all().difference(&FeatureGroup::NETIF_F_NEVER_CHANGE())
{
set.insert(*feature);
}
FeatureGroup(set)
};
}
&Static
}
pub fn NETIF_F_GSO_MASK() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup =
{
let inclusive_first_bit = NETIF_F::NETIF_F_GSO_SHIFT as u32;
let inclusive_last_bit = NETIF_F::NETIF_F_GSO_LAST as u32;
let mut hash_set = HashSet::with_capacity((inclusive_last_bit - inclusive_first_bit + 1) as usize);
for gso_mask_bit in inclusive_first_bit ..= inclusive_last_bit
{
hash_set.insert(unsafe { transmute(gso_mask_bit) });
}
FeatureGroup(hash_set)
};
}
&Static
}
#[inline(always)]
pub fn NETIF_F_CSUM_MASK() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_IP_CSUM_BIT,
NETIF_F_IPV6_CSUM_BIT,
NETIF_F_HW_CSUM_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_ALL_TSO() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_TSO_BIT,
NETIF_F_TSO6_BIT,
NETIF_F_TSO_ECN_BIT,
NETIF_F_TSO_MANGLEID_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_ALL_FCOE() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_FCOE_CRC_BIT,
NETIF_F_FCOE_MTU_BIT,
NETIF_F_FSO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_GSO_SOFTWARE() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup::NETIF_F_ALL_TSO().merge_with_one(NETIF_F_GSO_SCTP_BIT);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_ONE_FOR_ALL() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup::NETIF_F_GSO_SOFTWARE().merge_with_many
(
&[
NETIF_F_GSO_ROBUST_BIT,
NETIF_F_SG_BIT,
NETIF_F_HIGHDMA_BIT,
NETIF_F_FRAGLIST_BIT,
NETIF_F_VLAN_CHALLENGED_BIT,
]
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_ALL_FOR_ALL() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_NOCACHE_COPY_BIT,
NETIF_F_FSO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_UPPER_DISABLES() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_LRO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_SOFT_FEATURES() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_GSO_BIT,
NETIF_F_GRO_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_SOFT_FEATURES_OFF() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_GRO_FRAGLIST_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_VLAN_FEATURES() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
NETIF_F_HW_VLAN_CTAG_RX_BIT,
NETIF_F_HW_VLAN_CTAG_TX_BIT,
NETIF_F_HW_VLAN_STAG_FILTER_BIT,
NETIF_F_HW_VLAN_STAG_RX_BIT,
NETIF_F_HW_VLAN_STAG_TX_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn NETIF_F_GSO_ENCAP_ALL() -> &'static Self
{
lazy_static!
{
static ref Static: FeatureGroup = FeatureGroup
(
fast_secure_hash_set!
{
NETIF_F_GSO_GRE_BIT,
NETIF_F_GSO_GRE_CSUM_BIT,
NETIF_F_GSO_IPXIP4_BIT,
NETIF_F_GSO_IPXIP6_BIT,
NETIF_F_GSO_UDP_TUNNEL_BIT,
NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
}
);
}
&Static
}
#[inline(always)]
pub fn merge_with_one(&self, feature: Feature) -> Self
{
let mut feature_group = self.clone();
feature_group.insert(feature);
feature_group
}
#[inline(always)]
pub fn merge_with_many(&self, features: &[Feature]) -> Self
{
let mut feature_group = self.clone();
for feature in features
{
feature_group.insert(*feature);
}
feature_group
}
}