Skip to content

Commit

Permalink
feat: ✨ Use kernel version to determine if /proc/net/udp drops column…
Browse files Browse the repository at this point in the history
… can be read

Kernels prior to 2.6.27 do not provide a drops column for /proc/net/udp therefore a check is introduced to validate the current kernel version before reading the column

Add kernel version to SystemInfoInterface
  • Loading branch information
Michael Schleicher committed Aug 28, 2024
1 parent 6614785 commit d436d4a
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 16 deletions.
6 changes: 6 additions & 0 deletions procfs-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ pub trait SystemInfoInterface {
fn page_size(&self) -> u64;
/// Whether the system is little endian (true) or big endian (false).
fn is_little_endian(&self) -> bool;
fn kernel_version(&self) -> ProcResult<KernelVersion>;

#[cfg(feature = "chrono")]
fn boot_time(&self) -> ProcResult<chrono::DateTime<chrono::Local>> {
Expand All @@ -277,6 +278,7 @@ pub struct ExplicitSystemInfo {
pub ticks_per_second: u64,
pub page_size: u64,
pub is_little_endian: bool,
pub kernel_version: KernelVersion,
}

impl SystemInfoInterface for ExplicitSystemInfo {
Expand All @@ -295,6 +297,10 @@ impl SystemInfoInterface for ExplicitSystemInfo {
fn is_little_endian(&self) -> bool {
self.is_little_endian
}

fn kernel_version(&self) -> ProcResult<KernelVersion> {
Ok(self.kernel_version)
}
}

/// Values which can provide an output given the [SystemInfo].
Expand Down
62 changes: 47 additions & 15 deletions procfs-core/src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
//!
//! This module corresponds to the `/proc/net` directory and contains various information about the
//! networking layer.
use crate::ProcResult;
use crate::{build_internal_error, expect, from_iter, from_str};
use std::collections::HashMap;

use crate::{KernelVersion, ProcResult};
use bitflags::bitflags;
use std::collections::HashMap;
use std::io::BufRead;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::{path::PathBuf, str::FromStr};
Expand Down Expand Up @@ -296,9 +295,15 @@ impl super::FromBufReadSI for UdpNetEntries {
let uid = from_str!(u32, expect!(s.next(), "udp::uid"));
s.next(); // skip timeout
let inode = expect!(s.next(), "udp::inode");
s.next(); // skip ref
s.next(); // skip pointer
let drops = expect!(s.next(), "udp::drops");

let drops = match system_info.kernel_version() {
Ok(version) if version >= KernelVersion::new(2, 6, 27) => {
s.next(); // skip ref
s.next(); // skip pointer
expect!(s.next(), "udp::drops")
}
_ => "0", // Fallback if the kernel version does not support the drops column or the kernel version could not be read
};

vec.push(UdpNetEntry {
local_address: parse_addressport_str(local_address, system_info.is_little_endian())?,
Expand Down Expand Up @@ -1735,24 +1740,51 @@ UdpLite: 0 0 0 0 0 0 0 0 0
}

#[test]
fn test_udp_drops_debian_12() {
let data = r#" sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
624: 00000000:D77C 00000000:0000 07 00000000:00000000 00:00000000 00000000 104 0 3719666 2 000000008fba5196 0
824: 00000000:0044 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 14796 2 0000000051381d39 0
918: 00000000:00A2 00000000:0000 07 00000000:00000000 00:00000000 00000000 104 0 3719670 2 0000000048ae40a7 0
1270: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000 104 0 3719665 2 00000000357eb7c3 0
1357: 00000000:AA59 00000000:0000 07 00000000:00000000 00:00000000 00000000 104 0 3719668 2 000000000ed7b854 0"#;
fn test_udp_drops_debian_kernel_version_greater_2_6_27() {
let expected_drops = 42;
let data = format!(
r#" sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
1270: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000 104 0 3719665 2 00000000357eb7c3 {expected_drops}"#
);
let r = std::io::Cursor::new(data.as_bytes());
use crate::FromBufReadSI;
let res = UdpNetEntries::from_buf_read(
let entries = UdpNetEntries::from_buf_read(
r,
&crate::ExplicitSystemInfo {
boot_time_secs: 0,
ticks_per_second: 0,
page_size: 0,
is_little_endian: true,
kernel_version: "2.6.27".parse().unwrap(),
},
)
.unwrap();
let entry = entries.0.first().unwrap();

assert_eq!(entry.drops, expected_drops)
}

#[test]
fn test_udp_drops_debian_kernel_version_smaller_2_6_27() {
let data = format!(
r#" sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
1270: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000 104 0 3719665"#
);
assert!(res.is_ok())
let r = std::io::Cursor::new(data.as_bytes());
use crate::FromBufReadSI;
let entries = UdpNetEntries::from_buf_read(
r,
&crate::ExplicitSystemInfo {
boot_time_secs: 0,
ticks_per_second: 0,
page_size: 0,
is_little_endian: true,
kernel_version: "2.6.26".parse().unwrap(),
},
)
.unwrap();
let entry = entries.0.first().unwrap();

assert_eq!(entry.drops, 0)
}
}
4 changes: 4 additions & 0 deletions procfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ impl SystemInfoInterface for LocalSystemInfo {
fn is_little_endian(&self) -> bool {
u16::from_ne_bytes([0, 1]).to_le_bytes() == [0, 1]
}

fn kernel_version(&self) -> ProcResult<procfs_core::KernelVersion> {
KernelVersion::cached().map(Into::into)
}
}

const LOCAL_SYSTEM_INFO: LocalSystemInfo = LocalSystemInfo;
Expand Down
8 changes: 7 additions & 1 deletion procfs/src/sys/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Version {
Self {
major,
minor,
patch: u16::from_ne_bytes([lo, hi])
patch: u16::from_ne_bytes([lo, hi]),
}
}

Expand Down Expand Up @@ -145,6 +145,12 @@ impl cmp::PartialOrd for Version {
}
}

impl From<Version> for procfs_core::KernelVersion {
fn from(value: Version) -> Self {
Self::new(value.major, value.minor, value.patch)
}
}

/// Represents a kernel type
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Type {
Expand Down

0 comments on commit d436d4a

Please sign in to comment.