psutil/network/
net_io_couters.rs1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4use std::collections::HashMap;
5
6use derive_more::{Add, Sub, Sum};
7
8use crate::network::net_io_counters_pernic;
9use crate::{Bytes, Count, Result};
10
11#[cfg_attr(feature = "serde", serde(crate = "renamed_serde"))]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13#[derive(Clone, Debug, Add, Sum, Sub)]
14pub struct NetIoCounters {
15	pub(crate) bytes_sent: Bytes,
16	pub(crate) bytes_recv: Bytes,
17	pub(crate) packets_sent: Count,
18	pub(crate) packets_recv: Count,
19	pub(crate) err_in: Count,
20	pub(crate) err_out: Count,
21	pub(crate) drop_in: Count,
22	pub(crate) drop_out: Count,
23}
24
25impl NetIoCounters {
26	pub fn bytes_sent(&self) -> Bytes {
28		self.bytes_sent
29	}
30
31	pub fn bytes_recv(&self) -> Bytes {
33		self.bytes_recv
34	}
35
36	pub fn packets_sent(&self) -> Count {
38		self.packets_sent
39	}
40
41	pub fn packets_recv(&self) -> Count {
43		self.packets_recv
44	}
45
46	pub fn err_in(&self) -> Count {
49		self.err_in
50	}
51
52	pub fn err_out(&self) -> Count {
55		self.err_out
56	}
57
58	pub fn drop_in(&self) -> Count {
61		self.drop_in
62	}
63
64	pub fn drop_out(&self) -> Count {
67		self.drop_out
68	}
69}
70
71fn nowrap(prev: u64, current: u64, corrected: u64) -> u64 {
72	if current >= prev {
73		corrected + (current - prev)
74	} else {
75		corrected + current + ((u32::MAX as u64) - prev)
76	}
77}
78
79fn nowrap_struct(
80	prev: &NetIoCounters,
81	current: &NetIoCounters,
82	corrected: &NetIoCounters,
83) -> NetIoCounters {
84	NetIoCounters {
85		bytes_sent: nowrap(prev.bytes_sent, current.bytes_sent, corrected.bytes_sent),
86		bytes_recv: nowrap(prev.bytes_recv, current.bytes_recv, corrected.bytes_recv),
87		packets_sent: nowrap(
88			prev.packets_sent,
89			current.packets_sent,
90			corrected.packets_sent,
91		),
92		packets_recv: nowrap(
93			prev.packets_recv,
94			current.packets_recv,
95			corrected.packets_recv,
96		),
97		err_in: nowrap(prev.err_in, current.err_in, corrected.err_in),
98		err_out: nowrap(prev.err_out, current.err_out, corrected.err_out),
99		drop_in: nowrap(prev.drop_in, current.drop_in, corrected.drop_in),
100		drop_out: nowrap(prev.drop_out, current.drop_out, corrected.drop_out),
101	}
102}
103
104fn fix_io_counter_overflow(
105	prev: &HashMap<String, NetIoCounters>,
106	current: &HashMap<String, NetIoCounters>,
107	corrected: &HashMap<String, NetIoCounters>,
108) -> HashMap<String, NetIoCounters> {
109	current
110		.iter()
111		.map(|(name, current_counters)| {
112			if !prev.contains_key(name) || !corrected.contains_key(name) {
113				(name.clone(), current_counters.clone())
114			} else {
115				let prev_counters = &prev[name];
116				let corrected_counters = &corrected[name];
117
118				(
119					name.clone(),
120					nowrap_struct(prev_counters, current_counters, corrected_counters),
121				)
122			}
123		})
124		.collect()
125}
126
127#[derive(Debug, Clone, Default)]
129pub struct NetIoCountersCollector {
130	prev_net_io_counters_pernic: Option<HashMap<String, NetIoCounters>>,
131	corrected_net_io_counters_pernic: Option<HashMap<String, NetIoCounters>>,
132}
133
134impl NetIoCountersCollector {
135	pub fn net_io_counters(&mut self) -> Result<NetIoCounters> {
136		let sum = self.net_io_counters_pernic()?.into_values().sum();
137
138		Ok(sum)
139	}
140
141	pub fn net_io_counters_pernic(&mut self) -> Result<HashMap<String, NetIoCounters>> {
142		let io_counters = net_io_counters_pernic()?;
143
144		let corrected_counters = match (
145			&self.prev_net_io_counters_pernic,
146			&self.corrected_net_io_counters_pernic,
147		) {
148			(Some(prev), Some(corrected)) => fix_io_counter_overflow(prev, &io_counters, corrected),
149			_ => io_counters.clone(),
150		};
151
152		self.prev_net_io_counters_pernic = Some(io_counters);
153		self.corrected_net_io_counters_pernic = Some(corrected_counters.clone());
154
155		Ok(corrected_counters)
156	}
157}