diff --git a/src/common/network.rs b/src/common/network.rs index 150502640..023993c19 100644 --- a/src/common/network.rs +++ b/src/common/network.rs @@ -410,6 +410,20 @@ impl NetworkData { pub fn ip_networks(&self) -> &[IpNetwork] { self.inner.ip_networks() } + + /// Returns the Maximum Transfer Unit (MTU) of the interface. + /// + /// ```no_run + /// use sysinfo::Networks; + /// + /// let mut networks = Networks::new_with_refreshed_list(); + /// for (interface_name, network) in &networks { + /// println!("mtu: {}", network.mtu()); + /// } + /// ``` + pub fn mtu(&self) -> u64 { + self.inner.mtu() + } } /// MAC address for network interface. diff --git a/src/unix/apple/network.rs b/src/unix/apple/network.rs index f23d6f191..6c9715fc6 100644 --- a/src/unix/apple/network.rs +++ b/src/unix/apple/network.rs @@ -96,6 +96,7 @@ impl NetworksInner { } name.set_len(libc::strlen(pname)); let name = String::from_utf8_unchecked(name); + let mtu = (*if2m).ifm_data.ifi_mtu as u64; match self.interfaces.entry(name) { hash_map::Entry::Occupied(mut e) => { let interface = e.get_mut(); @@ -137,6 +138,7 @@ impl NetworksInner { old_errors_out, (*if2m).ifm_data.ifi_oerrors ); + if interface.mtu != mtu { interface.mtu = mtu } interface.updated = true; } hash_map::Entry::Vacant(e) => { @@ -167,6 +169,7 @@ impl NetworksInner { updated: true, mac_addr: MacAddr::UNSPECIFIED, ip_networks: vec![], + mtu, }, }); } @@ -196,6 +199,8 @@ pub(crate) struct NetworkDataInner { pub(crate) mac_addr: MacAddr, /// IP networks pub(crate) ip_networks: Vec, + /// Interface Maximum Transfer Unit (MTU) + mtu: u64, } impl NetworkDataInner { @@ -254,4 +259,8 @@ impl NetworkDataInner { pub(crate) fn ip_networks(&self) -> &[IpNetwork] { &self.ip_networks } + + pub(crate) fn mtu(&self) -> u64 { + self.mtu + } } diff --git a/src/unix/freebsd/network.rs b/src/unix/freebsd/network.rs index 486fcb1c6..68ebcd7aa 100644 --- a/src/unix/freebsd/network.rs +++ b/src/unix/freebsd/network.rs @@ -80,6 +80,7 @@ impl NetworksInner { } if let Some(name) = utils::c_buf_to_utf8_string(&data.ifmd_name) { let data = &data.ifmd_data; + let mtu = data.ifi_mtu as u64; match self.interfaces.entry(name) { hash_map::Entry::Occupied(mut e) => { let interface = e.get_mut(); @@ -91,6 +92,7 @@ impl NetworksInner { old_and_new!(interface, ifi_opackets, old_ifi_opackets, data); old_and_new!(interface, ifi_ierrors, old_ifi_ierrors, data); old_and_new!(interface, ifi_oerrors, old_ifi_oerrors, data); + if interface.mtu != mtu { interface.mtu = mtu } interface.updated = true; } hash_map::Entry::Vacant(e) => { @@ -115,6 +117,7 @@ impl NetworksInner { updated: true, mac_addr: MacAddr::UNSPECIFIED, ip_networks: vec![], + mtu, }, }); } @@ -151,6 +154,8 @@ pub(crate) struct NetworkDataInner { pub(crate) mac_addr: MacAddr, /// IP networks pub(crate) ip_networks: Vec, + /// Interface Maximum Transfer Unit (MTU) + mtu: u64, } impl NetworkDataInner { @@ -209,4 +214,8 @@ impl NetworkDataInner { pub(crate) fn ip_networks(&self) -> &[IpNetwork] { &self.ip_networks } + + pub(crate) fn mtu(&self) -> u64 { + self.mtu + } } diff --git a/src/unix/linux/network.rs b/src/unix/linux/network.rs index 6a1c1e44d..907402246 100644 --- a/src/unix/linux/network.rs +++ b/src/unix/linux/network.rs @@ -51,6 +51,7 @@ fn refresh_networks_list_from_sysfs( for entry in dir.flatten() { let parent = &entry.path().join("statistics"); + let entry_path = &entry.path(); let entry = match entry.file_name().into_string() { Ok(entry) => entry, Err(_) => continue, @@ -63,6 +64,8 @@ fn refresh_networks_list_from_sysfs( let tx_errors = read(parent, "tx_errors", &mut data); // let rx_compressed = read(parent, "rx_compressed", &mut data); // let tx_compressed = read(parent, "tx_compressed", &mut data); + let mtu = read(entry_path, "mtu", &mut data); + match interfaces.entry(entry) { hash_map::Entry::Occupied(mut e) => { let interface = e.get_mut(); @@ -76,6 +79,7 @@ fn refresh_networks_list_from_sysfs( old_and_new!(interface, tx_errors, old_tx_errors); // old_and_new!(e, rx_compressed, old_rx_compressed); // old_and_new!(e, tx_compressed, old_tx_compressed); + if interface.mtu != mtu { interface.mtu = mtu } interface.updated = true; } hash_map::Entry::Vacant(e) => { @@ -99,6 +103,7 @@ fn refresh_networks_list_from_sysfs( // old_rx_compressed: rx_compressed, // tx_compressed, // old_tx_compressed: tx_compressed, + mtu, updated: true, }, }); @@ -164,6 +169,8 @@ pub(crate) struct NetworkDataInner { /// MAC address pub(crate) mac_addr: MacAddr, pub(crate) ip_networks: Vec, + /// Interface Maximum Transfer Unit (MTU) + mtu: u64, // /// Indicates the number of compressed packets received by this // /// network device. This value might only be relevant for interfaces // /// that support packet compression (e.g: PPP). @@ -219,6 +226,9 @@ impl NetworkDataInner { // old_tx_compressed, // read(path, "tx_compressed", data) // ); + let mtu_path = &Path::new("/sys/class/net/").join(path); + let mtu = read(mtu_path, "mtu", data); + if self.mtu != mtu { self.mtu = mtu } } pub(crate) fn received(&self) -> u64 { @@ -276,6 +286,11 @@ impl NetworkDataInner { pub(crate) fn ip_networks(&self) -> &[IpNetwork] { &self.ip_networks } + + pub(crate) fn mtu(&self) -> u64 { + self.mtu + } + } #[cfg(test)] diff --git a/src/unknown/network.rs b/src/unknown/network.rs index 863858600..c76fbd204 100644 --- a/src/unknown/network.rs +++ b/src/unknown/network.rs @@ -82,4 +82,8 @@ impl NetworkDataInner { pub(crate) fn ip_networks(&self) -> &[IpNetwork] { &[] } + + pub(crate) fn mtu(&self) -> u64 { + 0 + } } diff --git a/src/windows/network.rs b/src/windows/network.rs index 15999493c..cd059aa7f 100644 --- a/src/windows/network.rs +++ b/src/windows/network.rs @@ -94,6 +94,8 @@ impl NetworksInner { Ok(s) => s, _ => continue, }; + + let mtu = ptr.Mtu as u64; match self.interfaces.entry(interface_name) { hash_map::Entry::Occupied(mut e) => { let interface = e.get_mut(); @@ -114,6 +116,7 @@ impl NetworksInner { ); old_and_new!(interface, errors_in, old_errors_in, ptr.InErrors); old_and_new!(interface, errors_out, old_errors_out, ptr.OutErrors); + if interface.mtu != mtu { interface.mtu = mtu } interface.updated = true; } hash_map::Entry::Vacant(e) => { @@ -137,6 +140,7 @@ impl NetworksInner { old_errors_out: ptr.OutErrors, mac_addr: MacAddr::UNSPECIFIED, ip_networks: vec![], + mtu, updated: true, }, }); @@ -179,6 +183,7 @@ impl NetworksInner { ); old_and_new!(interface, errors_in, old_errors_in, entry.InErrors); old_and_new!(interface, errors_out, old_errors_out, entry.OutErrors); + if interface.mtu != entry.Mtu as u64 { interface.mtu = entry.Mtu as u64 } } } } @@ -201,6 +206,8 @@ pub(crate) struct NetworkDataInner { updated: bool, pub(crate) mac_addr: MacAddr, pub(crate) ip_networks: Vec, + /// Interface Maximum Transfer Unit (MTU) + mtu: u64, } impl NetworkDataInner { @@ -259,4 +266,8 @@ impl NetworkDataInner { pub(crate) fn ip_networks(&self) -> &[IpNetwork] { &self.ip_networks } + + pub(crate) fn mtu(&self) -> u64 { + self.mtu + } }