#![cfg(any(
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd"
))]
#![allow(non_camel_case_types)]
use libc::{AF_INET, IFNAMSIZ, SOCK_DGRAM, close, ioctl, socket};
use std::ffi::CString;
#[cfg(target_os = "macos")]
use macos_subtypes::{ifm_subtype, map_subtype_to_bps};
#[cfg(target_os = "freebsd")]
use freebsd_subtypes::{ifm_subtype, map_subtype_to_bps};
#[cfg(target_os = "openbsd")]
use openbsd_subtypes::{ifm_subtype, map_subtype_to_bps};
#[cfg(target_os = "netbsd")]
use netbsd_subtypes::{ifm_subtype, map_subtype_to_bps};
pub(crate) fn get_link_speed(iface_name: &str) -> std::io::Result<LinkSpeed> {
Ok(get_ifmediareq(iface_name)?.into())
}
fn get_ifmediareq(iface_name: &str) -> std::io::Result<ifmediareq> {
let name = CString::new(iface_name)?;
let bytes = name.as_bytes_with_nul();
let mut ifmr: ifmediareq = unsafe { std::mem::zeroed() };
ifmr.ifm_name[..bytes.len()].copy_from_slice(&bytes);
let sock = unsafe { socket(AF_INET, SOCK_DGRAM, 0) };
if sock < 0 {
return Err(std::io::Error::last_os_error());
}
let ret = unsafe { ioctl(sock, SIOCGIFXMEDIA, &mut ifmr) };
unsafe {
close(sock);
}
if ret < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(ifmr)
}
pub(crate) struct LinkSpeed {
pub bps: Option<u64>,
pub auto_negotiate: bool,
}
impl From<ifmediareq> for LinkSpeed {
fn from(value: ifmediareq) -> Self {
let current_subtype = ifm_subtype(value.ifm_current);
let active_subtype = ifm_subtype(value.ifm_active);
let auto_negotiate = current_subtype == IFM_AUTO;
Self {
bps: map_subtype_to_bps(active_subtype).ok(),
auto_negotiate,
}
}
}
#[cfg(target_os = "openbsd")]
type ifmediareq_int = u64;
#[cfg(not(target_os = "openbsd"))]
type ifmediareq_int = i32;
#[repr(C)]
struct ifmediareq {
ifm_name: [u8; IFNAMSIZ],
ifm_current: ifmediareq_int,
ifm_mask: ifmediareq_int,
ifm_status: ifmediareq_int,
ifm_active: ifmediareq_int,
ifm_count: i32,
ifm_ulist: *mut ifmediareq_int,
}
#[cfg(target_os = "macos")]
const SIOCGIFXMEDIA: u64 = 0xc02c6948;
#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
const SIOCGIFXMEDIA: u64 = 0xc030698b;
#[cfg(all(target_os = "freebsd", target_arch = "x86"))]
const SIOCGIFXMEDIA: u32 = 0xc030698b;
#[cfg(any(target_os = "openbsd", target_os = "netbsd"))]
const SIOCGIFXMEDIA: u64 = 0xc02c6938;
const IFM_AUTO: i32 = 0;
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
const IFM_ETHER: i32 = 0x00000020;
const IFM_10_T: i32 = 3; const IFM_10_2: i32 = 4; const IFM_10_5: i32 = 5; const IFM_100_TX: i32 = 6; const IFM_100_FX: i32 = 7; const IFM_100_T4: i32 = 8; const IFM_100_VG: i32 = 9; const IFM_100_T2: i32 = 10; const IFM_1000_SX: i32 = 11; const IFM_10_STP: i32 = 12; const IFM_10_FL: i32 = 13; const IFM_1000_LX: i32 = 14; const IFM_1000_CX: i32 = 15; const IFM_1000_T: i32 = 16; const IFM_HPNA_1: i32 = 17;
#[cfg(target_os = "macos")]
mod macos_subtypes {
const IFM_TMASK_COMPAT: i32 = 0x0000001f;
const IFM_TMASK_EXT: i32 = 0x000f0000;
const IFM_TMASK_EXT_SHIFT: i32 = 11;
const IFM_TMASK: i32 = IFM_TMASK_COMPAT | IFM_TMASK_EXT;
pub(crate) fn ifm_subtype(x: i32) -> i32 {
x & IFM_TMASK
}
const fn ifm_x(x: i32) -> i32 {
((x) & IFM_TMASK_COMPAT)
| (((x) & (IFM_TMASK_EXT >> IFM_TMASK_EXT_SHIFT)) << IFM_TMASK_EXT_SHIFT)
}
const IFM_10G_SR: i32 = 18; const IFM_10G_LR: i32 = 19; const IFM_10G_CX4: i32 = 20; const IFM_10G_T: i32 = 21; const IFM_2500_T: i32 = 22; const IFM_5000_T: i32 = 23; const IFM_1000_CX_SGMII: i32 = 24; const IFM_1000_KX: i32 = 25; const IFM_10G_KX4: i32 = 26; const IFM_10G_KR: i32 = 27; const IFM_10G_CR1: i32 = 28; const IFM_10G_ER: i32 = 29; const IFM_20G_KR2: i32 = 30;
const IFM_2500_SX: i32 = ifm_x(32); const IFM_10G_TWINAX: i32 = ifm_x(33); const IFM_10G_TWINAX_LONG: i32 = ifm_x(34); const IFM_10G_LRM: i32 = ifm_x(35); const IFM_2500_KX: i32 = ifm_x(36); const IFM_40G_CR4: i32 = ifm_x(37); const IFM_40G_SR4: i32 = ifm_x(38); const IFM_50G_PCIE: i32 = ifm_x(39); const IFM_25G_PCIE: i32 = ifm_x(40); const IFM_1000_SGMII: i32 = ifm_x(41); const IFM_10G_SFI: i32 = ifm_x(42); const IFM_40G_XLPPI: i32 = ifm_x(43); const IFM_40G_LR4: i32 = ifm_x(44); const IFM_40G_KR4: i32 = ifm_x(45); const IFM_100G_CR4: i32 = ifm_x(47); const IFM_100G_SR4: i32 = ifm_x(48); const IFM_100G_KR4: i32 = ifm_x(49); const IFM_100G_LR4: i32 = ifm_x(50); const IFM_56G_R4: i32 = ifm_x(51); const IFM_100_T: i32 = ifm_x(52); const IFM_25G_CR: i32 = ifm_x(53); const IFM_25G_KR: i32 = ifm_x(54); const IFM_25G_SR: i32 = ifm_x(55); const IFM_50G_CR2: i32 = ifm_x(56); const IFM_50G_KR2: i32 = ifm_x(57); const IFM_25G_LR: i32 = ifm_x(58); const IFM_10G_AOC: i32 = ifm_x(59); const IFM_25G_ACC: i32 = ifm_x(60); const IFM_25G_AOC: i32 = ifm_x(61); const IFM_100_SGMII: i32 = ifm_x(62); const IFM_2500_X: i32 = ifm_x(63); const IFM_5000_KR: i32 = ifm_x(64); const IFM_25G_T: i32 = ifm_x(65); const IFM_25G_CR_S: i32 = ifm_x(66); const IFM_25G_CR1: i32 = ifm_x(67); const IFM_25G_KR_S: i32 = ifm_x(68); const IFM_5000_KR_S: i32 = ifm_x(69); const IFM_5000_KR1: i32 = ifm_x(70); const IFM_25G_AUI: i32 = ifm_x(71); const IFM_40G_XLAUI: i32 = ifm_x(72); const IFM_40G_XLAUI_AC: i32 = ifm_x(73); const IFM_40G_ER4: i32 = ifm_x(74); const IFM_50G_SR2: i32 = ifm_x(75); const IFM_50G_LR2: i32 = ifm_x(76); const IFM_50G_LAUI2_AC: i32 = ifm_x(77); const IFM_50G_LAUI2: i32 = ifm_x(78); const IFM_50G_AUI2_AC: i32 = ifm_x(79); const IFM_50G_AUI2: i32 = ifm_x(80); const IFM_50G_CP: i32 = ifm_x(81); const IFM_50G_SR: i32 = ifm_x(82); const IFM_50G_LR: i32 = ifm_x(83); const IFM_50G_FR: i32 = ifm_x(84); const IFM_50G_KR_PAM4: i32 = ifm_x(85); const IFM_25G_KR1: i32 = ifm_x(86); const IFM_50G_AUI1_AC: i32 = ifm_x(87); const IFM_50G_AUI1: i32 = ifm_x(88); const IFM_100G_CAUI4_AC: i32 = ifm_x(89); const IFM_100G_CAUI4: i32 = ifm_x(90); const IFM_100G_AUI4_AC: i32 = ifm_x(91); const IFM_100G_AUI4: i32 = ifm_x(92); const IFM_100G_CR_PAM4: i32 = ifm_x(93); const IFM_100G_KR_PAM4: i32 = ifm_x(94); const IFM_100G_CP2: i32 = ifm_x(95); const IFM_100G_SR2: i32 = ifm_x(96); const IFM_100G_DR: i32 = ifm_x(97); const IFM_100G_KR2_PAM4: i32 = ifm_x(98); const IFM_100G_CAUI2_AC: i32 = ifm_x(99); const IFM_100G_CAUI2: i32 = ifm_x(100); const IFM_100G_AUI2_AC: i32 = ifm_x(101); const IFM_100G_AUI2: i32 = ifm_x(102); const IFM_200G_CR4_PAM4: i32 = ifm_x(103); const IFM_200G_SR4: i32 = ifm_x(104); const IFM_200G_FR4: i32 = ifm_x(105); const IFM_200G_LR4: i32 = ifm_x(106); const IFM_200G_DR4: i32 = ifm_x(107); const IFM_200G_KR4_PAM4: i32 = ifm_x(108); const IFM_200G_AUI4_AC: i32 = ifm_x(109); const IFM_200G_AUI4: i32 = ifm_x(110); const IFM_200G_AUI8_AC: i32 = ifm_x(111); const IFM_200G_AUI8: i32 = ifm_x(112); const IFM_400G_FR8: i32 = ifm_x(113); const IFM_400G_LR8: i32 = ifm_x(114); const IFM_400G_DR4: i32 = ifm_x(115); const IFM_400G_AUI8_AC: i32 = ifm_x(116); const IFM_400G_AUI8: i32 = ifm_x(117);
pub(crate) fn map_subtype_to_bps(subtype: i32) -> std::io::Result<u64> {
use crate::os::unix::link_speed;
match subtype {
link_speed::IFM_HPNA_1 => Ok(1 * 1e6 as u64),
link_speed::IFM_10_T
| link_speed::IFM_10_2
| link_speed::IFM_10_5
| link_speed::IFM_10_STP
| link_speed::IFM_10_FL => Ok(10 * 1e6 as u64),
link_speed::IFM_100_TX
| link_speed::IFM_100_FX
| link_speed::IFM_100_T4
| link_speed::IFM_100_VG
| link_speed::IFM_100_T2
| IFM_100_T
| IFM_100_SGMII => Ok(100 * 1e6 as u64),
link_speed::IFM_1000_SX
| link_speed::IFM_1000_LX
| link_speed::IFM_1000_CX
| link_speed::IFM_1000_T
| IFM_1000_CX_SGMII
| IFM_1000_KX
| IFM_1000_SGMII => Ok(1000 * 1e6 as u64),
IFM_2500_T | IFM_2500_SX | IFM_2500_KX | IFM_2500_X => Ok(2500 * 1e6 as u64),
IFM_5000_T | IFM_5000_KR | IFM_5000_KR_S | IFM_5000_KR1 => Ok(5000 * 1e6 as u64),
IFM_10G_SR | IFM_10G_LR | IFM_10G_CX4 | IFM_10G_T | IFM_10G_KX4 | IFM_10G_KR
| IFM_10G_CR1 | IFM_10G_ER | IFM_10G_TWINAX | IFM_10G_TWINAX_LONG | IFM_10G_LRM
| IFM_10G_SFI | IFM_10G_AOC => Ok(10 * 1e9 as u64),
IFM_20G_KR2 => Ok(20 * 1e9 as u64),
IFM_25G_PCIE | IFM_25G_CR | IFM_25G_KR | IFM_25G_SR | IFM_25G_LR | IFM_25G_ACC
| IFM_25G_AOC | IFM_25G_T | IFM_25G_CR_S | IFM_25G_CR1 | IFM_25G_KR_S | IFM_25G_AUI
| IFM_25G_KR1 => Ok(25 * 1e9 as u64),
IFM_40G_CR4 | IFM_40G_SR4 | IFM_40G_XLPPI | IFM_40G_LR4 | IFM_40G_KR4
| IFM_40G_XLAUI | IFM_40G_XLAUI_AC | IFM_40G_ER4 => Ok(40 * 1e9 as u64),
IFM_50G_PCIE | IFM_50G_CR2 | IFM_50G_KR2 | IFM_50G_SR2 | IFM_50G_LR2
| IFM_50G_LAUI2_AC | IFM_50G_LAUI2 | IFM_50G_AUI2_AC | IFM_50G_AUI2 | IFM_50G_CP
| IFM_50G_SR | IFM_50G_LR | IFM_50G_FR | IFM_50G_KR_PAM4 | IFM_50G_AUI1_AC
| IFM_50G_AUI1 => Ok(50 * 1e9 as u64),
IFM_56G_R4 => Ok(56 * 1e9 as u64),
IFM_100G_CR4 | IFM_100G_SR4 | IFM_100G_KR4 | IFM_100G_LR4 | IFM_100G_CAUI4_AC
| IFM_100G_CAUI4 | IFM_100G_AUI4_AC | IFM_100G_AUI4 | IFM_100G_CR_PAM4
| IFM_100G_KR_PAM4 | IFM_100G_CP2 | IFM_100G_SR2 | IFM_100G_DR | IFM_100G_KR2_PAM4
| IFM_100G_CAUI2_AC | IFM_100G_CAUI2 | IFM_100G_AUI2_AC | IFM_100G_AUI2 => {
Ok(100 * 1e9 as u64)
}
IFM_200G_CR4_PAM4 | IFM_200G_SR4 | IFM_200G_FR4 | IFM_200G_LR4 | IFM_200G_DR4
| IFM_200G_KR4_PAM4 | IFM_200G_AUI4_AC | IFM_200G_AUI4 | IFM_200G_AUI8_AC
| IFM_200G_AUI8 => Ok(200 * 1e9 as u64),
IFM_400G_FR8 | IFM_400G_LR8 | IFM_400G_DR4 | IFM_400G_AUI8_AC | IFM_400G_AUI8 => {
Ok(400 * 1e9 as u64)
}
_ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"subtype {} does not map to a known link speed value",
subtype
),
)),
}
}
}
#[cfg(target_os = "freebsd")]
mod freebsd_subtypes {
const IFM_NMASK: i32 = 0x000000e0;
const IFM_TMASK: i32 = 0x0000001f;
const IFM_ETH_XTYPE: i32 = 0x00007800;
const IFM_ETH_XSHIFT: i32 = 6;
pub(crate) fn ifm_subtype(x: i32) -> i32 {
if x & IFM_NMASK == crate::os::unix::link_speed::IFM_ETHER {
x & (IFM_TMASK | IFM_ETH_XTYPE)
} else {
x & IFM_TMASK
}
}
const fn ifm_x(x: i32) -> i32 {
((x) & IFM_TMASK) | (((x) & (IFM_ETH_XTYPE >> IFM_ETH_XSHIFT)) << IFM_ETH_XSHIFT)
}
const IFM_10G_LR: i32 = 18; const IFM_10G_SR: i32 = 19; const IFM_10G_CX4: i32 = 20; const IFM_2500_SX: i32 = 21; const IFM_10G_TWINAX: i32 = 22; const IFM_10G_TWINAX_LONG: i32 = 23; const IFM_10G_LRM: i32 = 24; const IFM_UNKNOWN: i32 = 25; const IFM_10G_T: i32 = 26; const IFM_40G_CR4: i32 = 27; const IFM_40G_SR4: i32 = 28; const IFM_40G_LR4: i32 = 29; const IFM_1000_KX: i32 = 30;
const IFM_10G_KX4: i32 = ifm_x(32); const IFM_10G_KR: i32 = ifm_x(33); const IFM_10G_CR1: i32 = ifm_x(34); const IFM_20G_KR2: i32 = ifm_x(35); const IFM_2500_KX: i32 = ifm_x(36); const IFM_2500_T: i32 = ifm_x(37); const IFM_5000_T: i32 = ifm_x(38); const IFM_50G_PCIE: i32 = ifm_x(39); const IFM_25G_PCIE: i32 = ifm_x(40); const IFM_1000_SGMII: i32 = ifm_x(41); const IFM_10G_SFI: i32 = ifm_x(42); const IFM_40G_XLPPI: i32 = ifm_x(43); const IFM_1000_CX_SGMII: i32 = ifm_x(44); const IFM_40G_KR4: i32 = ifm_x(45); const IFM_10G_ER: i32 = ifm_x(46); const IFM_100G_CR4: i32 = ifm_x(47); const IFM_100G_SR4: i32 = ifm_x(48); const IFM_100G_KR4: i32 = ifm_x(49); const IFM_100G_LR4: i32 = ifm_x(50); const IFM_56G_R4: i32 = ifm_x(51); const IFM_100_T: i32 = ifm_x(52); const IFM_25G_CR: i32 = ifm_x(53); const IFM_25G_KR: i32 = ifm_x(54); const IFM_25G_SR: i32 = ifm_x(55); const IFM_50G_CR2: i32 = ifm_x(56); const IFM_50G_KR2: i32 = ifm_x(57); const IFM_25G_LR: i32 = ifm_x(58); const IFM_10G_AOC: i32 = ifm_x(59); const IFM_25G_ACC: i32 = ifm_x(60); const IFM_25G_AOC: i32 = ifm_x(61); const IFM_100_SGMII: i32 = ifm_x(62); const IFM_2500_X: i32 = ifm_x(63); const IFM_5000_KR: i32 = ifm_x(64); const IFM_25G_T: i32 = ifm_x(65); const IFM_25G_CR_S: i32 = ifm_x(66); const IFM_25G_CR1: i32 = ifm_x(67); const IFM_25G_KR_S: i32 = ifm_x(68); const IFM_5000_KR_S: i32 = ifm_x(69); const IFM_5000_KR1: i32 = ifm_x(70); const IFM_25G_AUI: i32 = ifm_x(71); const IFM_40G_XLAUI: i32 = ifm_x(72); const IFM_40G_XLAUI_AC: i32 = ifm_x(73); const IFM_40G_ER4: i32 = ifm_x(74); const IFM_50G_SR2: i32 = ifm_x(75); const IFM_50G_LR2: i32 = ifm_x(76); const IFM_50G_LAUI2_AC: i32 = ifm_x(77); const IFM_50G_LAUI2: i32 = ifm_x(78); const IFM_50G_AUI2_AC: i32 = ifm_x(79); const IFM_50G_AUI2: i32 = ifm_x(80); const IFM_50G_CP: i32 = ifm_x(81); const IFM_50G_SR: i32 = ifm_x(82); const IFM_50G_LR: i32 = ifm_x(83); const IFM_50G_FR: i32 = ifm_x(84); const IFM_50G_KR_PAM4: i32 = ifm_x(85); const IFM_25G_KR1: i32 = ifm_x(86); const IFM_50G_AUI1_AC: i32 = ifm_x(87); const IFM_50G_AUI1: i32 = ifm_x(88); const IFM_100G_CAUI4_AC: i32 = ifm_x(89); const IFM_100G_CAUI4: i32 = ifm_x(90); const IFM_100G_AUI4_AC: i32 = ifm_x(91); const IFM_100G_AUI4: i32 = ifm_x(92); const IFM_100G_CR_PAM4: i32 = ifm_x(93); const IFM_100G_KR_PAM4: i32 = ifm_x(94); const IFM_100G_CP2: i32 = ifm_x(95); const IFM_100G_SR2: i32 = ifm_x(96); const IFM_100G_DR: i32 = ifm_x(97); const IFM_100G_KR2_PAM4: i32 = ifm_x(98); const IFM_100G_CAUI2_AC: i32 = ifm_x(99); const IFM_100G_CAUI2: i32 = ifm_x(100); const IFM_100G_AUI2_AC: i32 = ifm_x(101); const IFM_100G_AUI2: i32 = ifm_x(102); const IFM_200G_CR4_PAM4: i32 = ifm_x(103); const IFM_200G_SR4: i32 = ifm_x(104); const IFM_200G_FR4: i32 = ifm_x(105); const IFM_200G_LR4: i32 = ifm_x(106); const IFM_200G_DR4: i32 = ifm_x(107); const IFM_200G_KR4_PAM4: i32 = ifm_x(108); const IFM_200G_AUI4_AC: i32 = ifm_x(109); const IFM_200G_AUI4: i32 = ifm_x(110); const IFM_200G_AUI8_AC: i32 = ifm_x(111); const IFM_200G_AUI8: i32 = ifm_x(112); const IFM_400G_FR8: i32 = ifm_x(113); const IFM_400G_LR8: i32 = ifm_x(114); const IFM_400G_DR4: i32 = ifm_x(115); const IFM_400G_AUI8_AC: i32 = ifm_x(116); const IFM_400G_AUI8: i32 = ifm_x(117); const IFM_50G_KR4: i32 = ifm_x(118); const IFM_40G_LM4: i32 = ifm_x(119);
pub(crate) fn map_subtype_to_bps(subtype: i32) -> std::io::Result<u64> {
use crate::os::unix::link_speed;
match subtype {
link_speed::IFM_HPNA_1 => Ok(1 * 1e6 as u64),
link_speed::IFM_10_T
| link_speed::IFM_10_2
| link_speed::IFM_10_5
| link_speed::IFM_10_STP
| link_speed::IFM_10_FL => Ok(10 * 1e6 as u64),
link_speed::IFM_100_TX
| link_speed::IFM_100_FX
| link_speed::IFM_100_T4
| link_speed::IFM_100_VG
| link_speed::IFM_100_T2
| IFM_100_T
| IFM_100_SGMII => Ok(100 * 1e6 as u64),
link_speed::IFM_1000_SX
| link_speed::IFM_1000_LX
| link_speed::IFM_1000_CX
| link_speed::IFM_1000_T
| IFM_1000_CX_SGMII
| IFM_1000_KX
| IFM_1000_SGMII => Ok(1000 * 1e6 as u64),
IFM_2500_T | IFM_2500_SX | IFM_2500_KX | IFM_2500_X => Ok(2500 * 1e6 as u64),
IFM_5000_T | IFM_5000_KR | IFM_5000_KR_S | IFM_5000_KR1 => Ok(5000 * 1e6 as u64),
IFM_10G_SR | IFM_10G_LR | IFM_10G_CX4 | IFM_10G_T | IFM_10G_KX4 | IFM_10G_KR
| IFM_10G_CR1 | IFM_10G_ER | IFM_10G_TWINAX | IFM_10G_TWINAX_LONG | IFM_10G_LRM
| IFM_10G_SFI | IFM_10G_AOC => Ok(10 * 1e9 as u64),
IFM_20G_KR2 => Ok(20 * 1e9 as u64),
IFM_25G_PCIE | IFM_25G_CR | IFM_25G_KR | IFM_25G_SR | IFM_25G_LR | IFM_25G_ACC
| IFM_25G_AOC | IFM_25G_T | IFM_25G_CR_S | IFM_25G_CR1 | IFM_25G_KR_S | IFM_25G_AUI
| IFM_25G_KR1 => Ok(25 * 1e9 as u64),
IFM_40G_CR4 | IFM_40G_SR4 | IFM_40G_XLPPI | IFM_40G_LR4 | IFM_40G_KR4
| IFM_40G_XLAUI | IFM_40G_XLAUI_AC | IFM_40G_ER4 | IFM_40G_LM4 => Ok(40 * 1e9 as u64),
IFM_50G_PCIE | IFM_50G_CR2 | IFM_50G_KR2 | IFM_50G_SR2 | IFM_50G_LR2
| IFM_50G_LAUI2_AC | IFM_50G_LAUI2 | IFM_50G_AUI2_AC | IFM_50G_AUI2 | IFM_50G_CP
| IFM_50G_SR | IFM_50G_LR | IFM_50G_FR | IFM_50G_KR_PAM4 | IFM_50G_AUI1_AC
| IFM_50G_AUI1 | IFM_50G_KR4 => Ok(50 * 1e9 as u64),
IFM_56G_R4 => Ok(56 * 1e9 as u64),
IFM_100G_CR4 | IFM_100G_SR4 | IFM_100G_KR4 | IFM_100G_LR4 | IFM_100G_CAUI4_AC
| IFM_100G_CAUI4 | IFM_100G_AUI4_AC | IFM_100G_AUI4 | IFM_100G_CR_PAM4
| IFM_100G_KR_PAM4 | IFM_100G_CP2 | IFM_100G_SR2 | IFM_100G_DR | IFM_100G_KR2_PAM4
| IFM_100G_CAUI2_AC | IFM_100G_CAUI2 | IFM_100G_AUI2_AC | IFM_100G_AUI2 => {
Ok(100 * 1e9 as u64)
}
IFM_200G_CR4_PAM4 | IFM_200G_SR4 | IFM_200G_FR4 | IFM_200G_LR4 | IFM_200G_DR4
| IFM_200G_KR4_PAM4 | IFM_200G_AUI4_AC | IFM_200G_AUI4 | IFM_200G_AUI8_AC
| IFM_200G_AUI8 => Ok(200 * 1e9 as u64),
IFM_400G_FR8 | IFM_400G_LR8 | IFM_400G_DR4 | IFM_400G_AUI8_AC | IFM_400G_AUI8 => {
Ok(400 * 1e9 as u64)
}
IFM_UNKNOWN | _ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"subtype {} does not map to a known link speed value",
subtype
),
)),
}
}
}
#[cfg(target_os = "openbsd")]
mod openbsd_subtypes {
const IFM_TMASK: u64 = 0x00000000000000ff;
pub(crate) fn ifm_subtype(x: i32) -> u64 {
(x as u64) & IFM_TMASK
}
const IFM_10G_LR: i32 = 18; const IFM_10G_SR: i32 = 19; const IFM_10G_CX4: i32 = 20; const IFM_2500_SX: i32 = 21; const IFM_10G_T: i32 = 22; const IFM_10G_SFP_CU: i32 = 23; const IFM_10G_LRM: i32 = 24; const IFM_40G_CR4: i32 = 25; const IFM_40G_SR4: i32 = 26; const IFM_40G_LR4: i32 = 27; const IFM_1000_KX: i32 = 28; const IFM_10G_KX4: i32 = 29; const IFM_10G_KR: i32 = 30; const IFM_10G_CR1: i32 = 31; const IFM_20G_KR2: i32 = 32; const IFM_2500_KX: i32 = 33; const IFM_2500_T: i32 = 34; const IFM_5000_T: i32 = 35; const IFM_1000_SGMII: i32 = 36; const IFM_10G_SFI: i32 = 37; const IFM_40G_XLPPI: i32 = 38; const IFM_1000_CX_SGMII: i32 = 39; const IFM_40G_KR4: i32 = 40; const IFM_10G_ER: i32 = 41; const IFM_100G_CR4: i32 = 42; const IFM_100G_SR4: i32 = 43; const IFM_100G_KR4: i32 = 44; const IFM_100G_LR4: i32 = 45; const IFM_56G_R4: i32 = 46; const IFM_25G_CR: i32 = 47; const IFM_25G_KR: i32 = 48; const IFM_25G_SR: i32 = 49; const IFM_50G_CR2: i32 = 50; const IFM_50G_KR2: i32 = 51; const IFM_25G_LR: i32 = 52; const IFM_25G_ER: i32 = 53; const IFM_10G_AOC: i32 = 54; const IFM_25G_AOC: i32 = 55; const IFM_40G_AOC: i32 = 56; const IFM_100G_AOC: i32 = 57;
pub(crate) fn map_subtype_to_bps(subtype: i32) -> std::io::Result<u64> {
use crate::os::unix::link_speed;
match subtype {
link_speed::IFM_HPNA_1 => Ok(1 * 1e6 as u64),
link_speed::IFM_10_T
| link_speed::IFM_10_2
| link_speed::IFM_10_5
| link_speed::IFM_10_STP
| link_speed::IFM_10_FL => Ok(10 * 1e6 as u64),
link_speed::IFM_100_TX
| link_speed::IFM_100_FX
| link_speed::IFM_100_T4
| link_speed::IFM_100_VG
| link_speed::IFM_100_T2 => Ok(100 * 1e6 as u64),
link_speed::IFM_1000_SX
| link_speed::IFM_1000_LX
| link_speed::IFM_1000_CX
| link_speed::IFM_1000_T
| IFM_1000_CX_SGMII
| IFM_1000_KX
| IFM_1000_SGMII => Ok(1000 * 1e6 as u64),
IFM_2500_SX | IFM_2500_KX | IFM_2500_T => Ok(2500 * 1e6 as u64),
IFM_5000_T => Ok(5000 * 1e6 as u64),
IFM_10G_LR | IFM_10G_SR | IFM_10G_CX4 | IFM_10G_T | IFM_10G_SFP_CU | IFM_10G_LRM
| IFM_10G_KX4 | IFM_10G_KR | IFM_10G_CR1 | IFM_10G_SFI | IFM_10G_ER | IFM_10G_AOC => {
Ok(10 * 1e9 as u64)
}
IFM_20G_KR2 => Ok(20 * 1e9 as u64),
IFM_25G_CR | IFM_25G_KR | IFM_25G_SR | IFM_25G_LR | IFM_25G_ER | IFM_25G_AOC => {
Ok(25 * 1e9 as u64)
}
IFM_40G_CR4 | IFM_40G_SR4 | IFM_40G_LR4 | IFM_40G_XLPPI | IFM_40G_KR4 | IFM_40G_AOC => {
Ok(40 * 1e9 as u64)
}
IFM_50G_CR2 | IFM_50G_KR2 => Ok(50 * 1e9 as u64),
IFM_56G_R4 => Ok(56 * 1e9 as u64),
IFM_100G_CR4 | IFM_100G_SR4 | IFM_100G_KR4 | IFM_100G_LR4 | IFM_100G_AOC => {
Ok(100 * 1e9 as u64)
}
_ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"subtype {} does not map to a known link speed value",
subtype
),
)),
}
}
}
#[cfg(target_os = "netbsd")]
mod netbsd_subtypes {
const IFM_NMASK: i32 = 0x000000e0;
const IFM_TMASK: i32 = 0x0000001f;
const _IFM_ETH_XTMASK: i32 = 0x0000e000;
const IFM_ETH_XSHIFT: i32 = 13 - 5;
pub(crate) fn ifm_subtype(x: i32) -> i32 {
if (x & IFM_NMASK) == crate::os::unix::link_speed::IFM_ETHER {
x & (IFM_TMASK | _IFM_ETH_XTMASK)
} else {
x & IFM_TMASK
}
}
const fn ifm_ex(x: i32) -> i32 {
((x) & IFM_TMASK) | (((x) & (_IFM_ETH_XTMASK >> IFM_ETH_XSHIFT)) << IFM_ETH_XSHIFT)
}
const IFM_10G_LR: i32 = 18; const IFM_10G_SR: i32 = 19; const IFM_10G_CX4: i32 = 20; const IFM_2500_SX: i32 = 21; const IFM_1000_BX10: i32 = 22; const IFM_10G_TWINAX: i32 = 23; const IFM_10G_TWINAX_LONG: i32 = 24; const IFM_10G_LRM: i32 = 25; const IFM_10G_T: i32 = 26; const IFM_1000_KX: i32 = 27; const IFM_2500_KX: i32 = 28; const IFM_2500_T: i32 = 29; const IFM_5000_T: i32 = 30; const IFM_1000_SGMII: i32 = ifm_ex(32); const IFM_5000_KR: i32 = ifm_ex(33); const IFM_10G_AOC: i32 = ifm_ex(34); const IFM_10G_CR1: i32 = ifm_ex(35); const IFM_10G_ER: i32 = ifm_ex(36); const IFM_10G_KR: i32 = ifm_ex(37); const IFM_10G_KX4: i32 = ifm_ex(38); const IFM_10G_LX4: i32 = ifm_ex(39); const IFM_10G_SFI: i32 = ifm_ex(40); const IFM_10G_ZR: i32 = ifm_ex(41); const IFM_20G_KR2: i32 = ifm_ex(42); const IFM_25G_AOC: i32 = ifm_ex(43); const IFM_25G_AUI: i32 = ifm_ex(44); const IFM_25G_CR: i32 = ifm_ex(45); const IFM_25G_ACC: i32 = ifm_ex(46); const IFM_25G_CR_S: i32 = ifm_ex(47); const IFM_25G_ER: i32 = ifm_ex(48); const IFM_25G_KR: i32 = ifm_ex(49); const IFM_25G_KR_S: i32 = ifm_ex(50); const IFM_25G_LR: i32 = ifm_ex(51); const IFM_25G_SR: i32 = ifm_ex(52); const IFM_25G_T: i32 = ifm_ex(53); const IFM_40G_AOC: i32 = ifm_ex(54); const IFM_40G_CR4: i32 = ifm_ex(55); const IFM_40G_ER4: i32 = ifm_ex(56); const IFM_40G_FR: i32 = ifm_ex(57); const IFM_40G_KR4: i32 = ifm_ex(58); const IFM_40G_LR4: i32 = ifm_ex(59); const IFM_40G_SR4: i32 = ifm_ex(60); const IFM_40G_T: i32 = ifm_ex(61); const IFM_40G_XLPPI: i32 = ifm_ex(62); const IFM_50G_AUI1: i32 = ifm_ex(63); const IFM_50G_AUI2: i32 = ifm_ex(64); const IFM_50G_CR: i32 = ifm_ex(65); const IFM_50G_CR2: i32 = ifm_ex(66); const IFM_50G_FR: i32 = ifm_ex(67); const IFM_50G_KR: i32 = ifm_ex(68); const IFM_50G_KR2: i32 = ifm_ex(69); const IFM_50G_LAUI2: i32 = ifm_ex(70); const IFM_50G_LR: i32 = ifm_ex(71); const IFM_50G_SR: i32 = ifm_ex(73); const IFM_50G_SR2: i32 = ifm_ex(74); const IFM_56G_R4: i32 = ifm_ex(75); const IFM_100G_CR2: i32 = ifm_ex(76); const IFM_100G_CR4: i32 = ifm_ex(77); const IFM_100G_CR10: i32 = ifm_ex(78); const IFM_100G_DR: i32 = ifm_ex(79); const IFM_100G_ER4: i32 = ifm_ex(80); const IFM_100G_KP4: i32 = ifm_ex(81); const IFM_100G_KR2: i32 = ifm_ex(82); const IFM_100G_KR4: i32 = ifm_ex(83); const IFM_100G_LR4: i32 = ifm_ex(84); const IFM_100G_SR2: i32 = ifm_ex(85); const IFM_100G_SR4: i32 = ifm_ex(86); const IFM_100G_SR10: i32 = ifm_ex(87); const IFM_200G_CR2: i32 = ifm_ex(88); const IFM_200G_CR4: i32 = ifm_ex(89); const IFM_200G_DR4: i32 = ifm_ex(90); const IFM_200G_FR4: i32 = ifm_ex(91); const IFM_200G_KR2: i32 = ifm_ex(92); const IFM_200G_KR4: i32 = ifm_ex(93); const IFM_200G_LR4: i32 = ifm_ex(94); const IFM_200G_SR4: i32 = ifm_ex(95); const IFM_400G_CR4: i32 = ifm_ex(96); const IFM_400G_DR4: i32 = ifm_ex(97); const IFM_400G_FR8: i32 = ifm_ex(98); const IFM_400G_KR4: i32 = ifm_ex(99); const IFM_400G_LR8: i32 = ifm_ex(100); const IFM_400G_SR16: i32 = ifm_ex(101); const IFM_100G_ACC: i32 = ifm_ex(102); const IFM_100G_AOC: i32 = ifm_ex(103); const IFM_100G_FR: i32 = ifm_ex(104); const IFM_100G_LR: i32 = ifm_ex(105); const IFM_200G_ER4: i32 = ifm_ex(106); const IFM_400G_ER8: i32 = ifm_ex(107); const IFM_400G_FR4: i32 = ifm_ex(108); const IFM_400G_LR4: i32 = ifm_ex(109); const IFM_400G_SR4_2: i32 = ifm_ex(110); const IFM_400G_SR8: i32 = ifm_ex(111);
pub(crate) fn map_subtype_to_bps(subtype: i32) -> std::io::Result<u64> {
use crate::os::unix::link_speed;
match subtype {
link_speed::IFM_HPNA_1 => Ok(1 * 1e6 as u64),
link_speed::IFM_10_T
| link_speed::IFM_10_2
| link_speed::IFM_10_5
| link_speed::IFM_10_STP
| link_speed::IFM_10_FL => Ok(10 * 1e6 as u64),
link_speed::IFM_100_TX
| link_speed::IFM_100_FX
| link_speed::IFM_100_T4
| link_speed::IFM_100_VG
| link_speed::IFM_100_T2 => Ok(100 * 1e6 as u64),
link_speed::IFM_1000_SX
| link_speed::IFM_1000_LX
| link_speed::IFM_1000_CX
| link_speed::IFM_1000_T
| IFM_1000_BX10
| IFM_1000_KX
| IFM_1000_SGMII => Ok(1000 * 1e6 as u64),
IFM_2500_SX | IFM_2500_KX | IFM_2500_T => Ok(2500 * 1e6 as u64),
IFM_5000_T | IFM_5000_KR => Ok(5000 * 1e6 as u64),
IFM_10G_LR | IFM_10G_SR | IFM_10G_CX4 | IFM_10G_TWINAX | IFM_10G_TWINAX_LONG
| IFM_10G_LRM | IFM_10G_T | IFM_10G_AOC | IFM_10G_CR1 | IFM_10G_ER | IFM_10G_KR
| IFM_10G_KX4 | IFM_10G_LX4 | IFM_10G_SFI | IFM_10G_ZR => Ok(10 * 1e9 as u64),
IFM_20G_KR2 => Ok(20 * 1e9 as u64),
IFM_25G_AOC | IFM_25G_AUI | IFM_25G_CR | IFM_25G_ACC | IFM_25G_CR_S | IFM_25G_ER
| IFM_25G_KR | IFM_25G_KR_S | IFM_25G_LR | IFM_25G_SR | IFM_25G_T => {
Ok(25 * 1e9 as u64)
}
IFM_40G_AOC | IFM_40G_CR4 | IFM_40G_ER4 | IFM_40G_FR | IFM_40G_KR4 | IFM_40G_LR4
| IFM_40G_SR4 | IFM_40G_T | IFM_40G_XLPPI => Ok(40 * 1e9 as u64),
IFM_50G_AUI1 | IFM_50G_AUI2 | IFM_50G_CR | IFM_50G_CR2 | IFM_50G_FR | IFM_50G_KR
| IFM_50G_KR2 | IFM_50G_LAUI2 | IFM_50G_LR | IFM_50G_SR | IFM_50G_SR2 => {
Ok(50 * 1e9 as u64)
}
IFM_56G_R4 => Ok(56 * 1e9 as u64),
IFM_100G_CR2 | IFM_100G_CR4 | IFM_100G_CR10 | IFM_100G_DR | IFM_100G_ER4
| IFM_100G_KP4 | IFM_100G_KR2 | IFM_100G_KR4 | IFM_100G_LR4 | IFM_100G_SR2
| IFM_100G_SR4 | IFM_100G_SR10 | IFM_100G_ACC | IFM_100G_AOC | IFM_100G_FR
| IFM_100G_LR => Ok(100 * 1e9 as u64),
IFM_200G_CR2 | IFM_200G_CR4 | IFM_200G_DR4 | IFM_200G_FR4 | IFM_200G_KR2
| IFM_200G_KR4 | IFM_200G_LR4 | IFM_200G_SR4 | IFM_200G_ER4 => Ok(200 * 1e9 as u64),
IFM_400G_CR4 | IFM_400G_DR4 | IFM_400G_FR8 | IFM_400G_KR4 | IFM_400G_LR8
| IFM_400G_SR16 | IFM_400G_ER8 | IFM_400G_FR4 | IFM_400G_LR4 | IFM_400G_SR4_2
| IFM_400G_SR8 => Ok(400 * 1e9 as u64),
_ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"subtype {} does not map to a known link speed value",
subtype
),
)),
}
}
}