diff --git a/Cargo.lock b/Cargo.lock index 66297e4..a5dbeea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,32 +72,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "cc" version = "1.2.56" @@ -154,7 +128,7 @@ dependencies = [ "ansi_term", "atty", "bitflags 1.3.2", - "strsim 0.8.0", + "strsim", "textwrap", "unicode-width", "vec_map", @@ -178,41 +152,6 @@ dependencies = [ "libc", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.11.1", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn", -] - [[package]] name = "deranged" version = "0.5.7" @@ -222,43 +161,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - [[package]] name = "env_logger" version = "0.8.4" @@ -294,12 +196,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" @@ -320,18 +216,6 @@ dependencies = [ "wasip3", ] -[[package]] -name = "getset" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" -dependencies = [ - "proc-macro-error2", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "glob" version = "0.3.3" @@ -388,12 +272,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "indexmap" version = "2.13.0" @@ -462,21 +340,23 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "maybe-async" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "memchr" version = "2.8.0" @@ -484,32 +364,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] -name = "neli" -version = "0.7.4" +name = "netlink-bindings" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f9786d56d972959e1408b6a93be6af13b9c1392036c5c1fafa08a1b0c6ee87" -dependencies = [ - "bitflags 2.11.0", - "byteorder", - "derive_builder", - "getset", - "libc", - "log", - "neli-proc-macros", - "parking_lot", -] +checksum = "e639b3a966932d8ab55cfc1e606e5421aef3d30a2610284535b854f11f6e4b44" [[package]] -name = "neli-proc-macros" -version = "0.2.2" +name = "netlink-socket2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d8d08c6e98f20a62417478ebf7be8e1425ec9acecc6f63e22da633f6b71609" +checksum = "ffef37f26cf649b9f473ccc00fa52d419511225a7b3a2093bf16dc8673ab9cf1" dependencies = [ - "either", - "proc-macro2", - "quote", - "serde", - "syn", + "libc", + "maybe-async", + "netlink-bindings", ] [[package]] @@ -528,29 +396,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - [[package]] name = "peeking_take_while" version = "0.1.2" @@ -573,28 +418,6 @@ dependencies = [ "syn", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -636,15 +459,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.11.0", -] - [[package]] name = "regex" version = "1.12.3" @@ -704,12 +518,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "semver" version = "1.0.27" @@ -723,7 +531,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", - "serde_derive", ] [[package]] @@ -765,12 +572,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - [[package]] name = "socket2" version = "0.6.2" @@ -786,10 +587,11 @@ name = "sqm-autorate-rust" version = "0.2.0" dependencies = [ "anyhow", - "bytemuck", "icmp-socket", + "libc", "log", - "neli", + "netlink-bindings", + "netlink-socket2", "rand", "rust-uci", "rustix", @@ -803,12 +605,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - [[package]] name = "syn" version = "2.0.117" diff --git a/Cargo.toml b/Cargo.toml index b8f652c..d991d0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,13 +20,14 @@ strip = "symbols" [dependencies] anyhow = "1.0" -bytemuck = { version = "1.25.0", features = ["derive"] } icmp-socket = "0.4.0" -neli = "0.7" +netlink-bindings = { version = "0.2", features = ["rt-link", "tc"] } +netlink-socket2 = "0.2" rand = "0.10" rustix = { version = "1.1", features = ["fs", "thread", "time"] } rust-uci = { version = "0.1", optional = true } thiserror = "2.0" +libc = "0.2" [dependencies.log] features = ["std"] diff --git a/src/netlink.rs b/src/netlink.rs index ecd584a..7e24f08 100644 --- a/src/netlink.rs +++ b/src/netlink.rs @@ -1,31 +1,23 @@ -use bytemuck::AnyBitPattern; -use bytemuck::checked::{CheckedCastError, try_from_bytes}; -use neli::consts::nl::NlmF; -use neli::consts::rtnl::{Arphrd, Iff, Ifla, RtAddrFamily, Rtm, Tca}; -use neli::consts::socket::NlFamily; -use neli::err::{RouterError, SerError}; -use neli::nl::{NlPayload, Nlmsghdr}; -use neli::router::synchronous::NlRouter; -use neli::rtnl::{Ifinfomsg, IfinfomsgBuilder, RtattrBuilder, Tcmsg, TcmsgBuilder}; -use neli::types::{Buffer, RtBuffer}; -use neli::utils::Groups; use std::io; use std::str::Utf8Error; + +use netlink_bindings::{rt_link, tc}; +use netlink_socket2::NetlinkSocket; use thiserror::Error; #[derive(Debug, Error)] pub enum NetlinkError { - #[error("Couldn't deserialize to struct: {0}")] - Deserialization(CheckedCastError), - - #[error("Couldn't find intreface `{0}`")] + #[error("Couldn't find interface `{0}`")] InterfaceNotFound(String), - #[error("Netlink interface error")] - NlInterfaceError(#[from] RouterError), + #[error("Netlink error: {0}")] + Netlink(#[from] io::Error), + + #[error("Netlink reply error: {0}")] + Reply(#[from] netlink_socket2::ReplyError), #[error("Something went wrong while finding qdisc")] - NlQdiscError(#[from] RouterError), + NlQdiscError(String), #[error("Couldn't find CAKE qdisc on interface `{0}`")] NoQdiscFound(String), @@ -33,150 +25,49 @@ pub enum NetlinkError { #[error("Couldn't find interface statistics: `{0}`")] NoInterfaceStatsFound(String), - #[error("Couldn't open Netlink socket")] - OpenSocket(#[from] io::Error), - - #[error("Serialization error")] - Serialization(#[from] SerError), - #[error("Error happened while parsing UTF-8 string")] Utf8Error(#[from] Utf8Error), - #[error("Invalid Rtm type (expected {expected:?}, found {found:?})")] - WrongType { expected: Rtm, found: Rtm }, + #[error("Invalid reply type")] + InvalidReply, } #[derive(Clone, Copy, Debug)] pub struct Qdisc { - ifindex: i32, - parent: u32, -} - -#[derive(AnyBitPattern, Copy, Clone, Default, Debug)] -#[repr(C)] -pub struct RtnlLinkStats64 { - pub rx_packets: u64, - pub tx_packets: u64, - pub rx_bytes: u64, - pub tx_bytes: u64, - pub rx_errors: u64, - pub tx_errors: u64, - pub rx_dropped: u64, - pub tx_dropped: u64, - pub multicast: u64, - pub collisions: u64, - pub rx_length_errors: u64, - pub rx_over_errors: u64, - pub rx_crc_errors: u64, - pub rx_frame_errors: u64, - pub rx_fifo_errors: u64, - pub rx_missed_errors: u64, - pub tx_aborted_errors: u64, - pub tx_carrier_errors: u64, - pub tx_fifo_errors: u64, - pub tx_heartbeat_errors: u64, - pub tx_window_errors: u64, - pub rx_compressed: u64, - pub tx_compressed: u64, - pub rx_nohandler: u64, -} - -pub enum TcaCake { - BaseRate64 = 2, + pub ifindex: i32, + pub parent: u32, } pub struct Netlink {} impl Netlink { - fn nl_interface_get( - socket: &NlRouter, - ifname: &str, - ) -> Result, NetlinkError> - { - let mut attrs = RtBuffer::new(); - - const RTEXT_FILTER_VF: i32 = 1 << 0; - - let attr_ifname = RtattrBuilder::default() - .rta_type(Ifla::Ifname) - .rta_payload(ifname) - .build() - .unwrap(); - let attr_ext_mask = RtattrBuilder::default() - .rta_type(Ifla::ExtMask) - .rta_payload(RTEXT_FILTER_VF) - .build() - .unwrap(); - attrs.push(attr_ifname); - attrs.push(attr_ext_mask); - - let if_msg = IfinfomsgBuilder::default() - .ifi_family(RtAddrFamily::Unspecified) - .ifi_type(Arphrd::None) - .ifi_index(-1) - .ifi_flags(Iff::empty()) - .ifi_change(Iff::empty()) - .rtattrs(attrs) - .build() - .unwrap(); - - let recv = socket.send::<_, _, Rtm, Ifinfomsg>( - Rtm::Getlink, - NlmF::REQUEST | NlmF::ACK, - NlPayload::Payload(if_msg), - )?; - - Ok(recv) - } - pub fn find_interface(ifname: &str) -> Result { - let (socket, _) = NlRouter::connect(NlFamily::Route, None, Groups::empty()).unwrap(); + let mut socket = NetlinkSocket::new(); - let recv = Self::nl_interface_get(&socket, ifname)?; + let mut request = rt_link::Request::new() + .op_getlink_do_request(&Default::default()); + request.encode().push_ifname_bytes(ifname.as_bytes()); - for response in recv { - let header: Nlmsghdr = response?; - - if header.nl_type() != &Rtm::Newlink { - return Err(NetlinkError::WrongType { - expected: Rtm::Newlink, - found: *header.nl_type(), - }); - } - - if let NlPayload::Payload(p) = header.nl_payload() { - return Ok(*p.ifi_index()); - } - } - - // we shouldn't reach here - Err(NetlinkError::InterfaceNotFound(ifname.to_string())) + let mut iter = socket.request(&request)?; + let (header, _) = iter.recv_one()?; + Ok(header.ifi_index()) } - pub fn get_interface_stats(ifname: &str) -> Result { - let (socket, _) = NlRouter::connect(NlFamily::Route, None, Groups::empty()).unwrap(); + pub fn get_interface_stats(ifname: &str) -> Result<(u64, u64), NetlinkError> { + let mut socket = NetlinkSocket::new(); - let recv = Self::nl_interface_get(&socket, ifname)?; + let mut request = rt_link::Request::new() + .op_getlink_do_request(&Default::default()); + request.encode() + .push_ifname_bytes(ifname.as_bytes()) + .push_ext_mask(1 /* RTEXT_FILTER_VF */); - for response in recv { - let header: Nlmsghdr = response?; - - if header.nl_type() != &Rtm::Newlink { - return Err(NetlinkError::WrongType { - expected: Rtm::Newlink, - found: *header.nl_type(), - }); - } - - if let NlPayload::Payload(p) = header.nl_payload() { - for attr in p.rtattrs().iter() { - if attr.rta_type() == &Ifla::Stats64 { - let buf = attr.rta_payload().as_ref(); - let stats: &RtnlLinkStats64 = try_from_bytes::(buf) - .map_err(|e| NetlinkError::Deserialization(e))?; - - return Ok(stats.clone()); - } + let mut iter = socket.request(&request)?; + while let Some(reply) = iter.recv() { + let (_, attrs) = reply?; + for attr in attrs { + if let Ok(rt_link::OpGetlinkDoReply::Stats64(stats)) = attr { + return Ok((stats.rx_bytes(), stats.tx_bytes())); } } } @@ -185,55 +76,30 @@ impl Netlink { } pub fn qdisc_from_ifindex(ifindex: i32) -> Result { - let (socket, _) = NlRouter::connect(NlFamily::Route, None, Groups::empty()).unwrap(); - let tc_msg = TcmsgBuilder::default() - .tcm_family(u8::from(RtAddrFamily::Unspecified)) - .tcm_ifindex(ifindex) - .tcm_handle(0) - .tcm_parent(0) - .tcm_info(0) - .rtattrs(RtBuffer::new()) - .build() - .unwrap(); + let mut socket = NetlinkSocket::new(); + let header = tc::PushTcmsg::new(); + let request = tc::Request::new().op_getqdisc_dump_request(&header); - let recv = socket.send::<_, _, Rtm, Tcmsg>( - Rtm::Getqdisc, - NlmF::REQUEST | NlmF::DUMP, - NlPayload::Payload(tc_msg), - )?; + let mut iter = socket.request(&request)?; + while let Some(reply) = iter.recv() { + let (header, attrs) = reply?; - for response in recv { - let header: Nlmsghdr = response?; - - if let NlPayload::Payload(p) = header.nl_payload() { - if header.nl_type() != &Rtm::Newqdisc { - return Err(NetlinkError::WrongType { - expected: Rtm::Newqdisc, - found: *header.nl_type(), - }); - } - - if *p.tcm_ifindex() == ifindex { - let mut _type = ""; - - for attr in p.rtattrs().iter() { - if attr.rta_type() == &Tca::Kind { - let buff = attr.rta_payload().as_ref(); - _type = std::str::from_utf8(buff)?.trim_end_matches('\0'); - // Null terminator is valid UTF-8, but breaks comparison, so we remove it + if header.ifindex() == ifindex { + let mut is_cake = false; + for attr in attrs { + if let Ok(tc::OpGetqdiscDumpReply::Kind(kind)) = attr { + if kind.to_str().map_err(|_| NetlinkError::NlQdiscError("Invalid UTF-8".to_string()))? == "cake" { + is_cake = true; + break; } } + } - let type_to_look_for = "cake"; - - if _type.eq(type_to_look_for) { - let qdisc = Qdisc { - ifindex: *p.tcm_ifindex() as i32, - parent: *p.tcm_parent(), - }; - - return Ok(qdisc); - } + if is_cake { + return Ok(Qdisc { + ifindex, + parent: header.parent(), + }); } } } @@ -247,53 +113,24 @@ impl Netlink { } pub fn set_qdisc_rate(qdisc: Qdisc, bandwidth_kbit: u64) -> Result<(), NetlinkError> { - let (socket, _) = NlRouter::connect(NlFamily::Route, None, Groups::empty()).unwrap(); + let mut socket = NetlinkSocket::new(); let bandwidth = bandwidth_kbit * 1000 / 8; - let mut attrs = RtBuffer::new(); + let mut header = tc::PushTcmsg::new(); + header.set_ifindex(qdisc.ifindex); + header.set_parent(qdisc.parent); - let attr_type = RtattrBuilder::default() - .rta_type(Tca::Kind) - .rta_payload("cake") - .build() - .unwrap(); - let attr_options = RtattrBuilder::default() - .rta_type(Tca::Options) - .rta_payload(Buffer::from(Vec::new())) - .build() - .unwrap() - .nest( - &RtattrBuilder::default() - .rta_type(TcaCake::BaseRate64 as u16) - .rta_payload(bandwidth) - .build() - .unwrap(), - )?; + let mut request = tc::Request::new() + .set_change() + .op_newqdisc_do_request(&header); + request.encode() + .push_kind(c"cake") + .nested_options_cake() + .push_base_rate64(bandwidth) + .end_nested(); - attrs.push(attr_type); - attrs.push(attr_options); - - let tc_msg = TcmsgBuilder::default() - .tcm_family(u8::from(RtAddrFamily::Unspecified)) - .tcm_ifindex(qdisc.ifindex) - .tcm_handle(0) - .tcm_parent(qdisc.parent) - .tcm_info(0) - .rtattrs(attrs) - .build() - .unwrap(); - - let recv = socket - .send::<_, _, Rtm, Tcmsg>( - Rtm::Newqdisc, - NlmF::REQUEST | NlmF::ACK, - NlPayload::Payload(tc_msg), - ) - .map_err(|e| NetlinkError::NlQdiscError(e))?; - - for msg in recv { - let _ = msg?; - } + let mut iter = socket.request(&request)?; + iter.recv_ack()?; Ok(()) } diff --git a/src/ratecontroller.rs b/src/ratecontroller.rs index 341bfa5..c065d4a 100644 --- a/src/ratecontroller.rs +++ b/src/ratecontroller.rs @@ -62,10 +62,8 @@ fn get_interface_stats( down_direction: StatsDirection, up_direction: StatsDirection, ) -> Result<(i128, i128), RatecontrolError> { - let down_stats = Netlink::get_interface_stats(config.download_interface.as_str())?; - let up_stats = Netlink::get_interface_stats(config.upload_interface.as_str())?; - let (down_rx, down_tx) = (down_stats.rx_bytes, down_stats.tx_bytes); - let (up_rx, up_tx) = (up_stats.rx_bytes, up_stats.tx_bytes); + let (down_rx, down_tx) = Netlink::get_interface_stats(config.download_interface.as_str())?; + let (up_rx, up_tx) = Netlink::get_interface_stats(config.upload_interface.as_str())?; let rx_bytes = match down_direction { StatsDirection::RX => down_rx,