From: Stefan Hanreich <s.hanreich@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 2/2] metric_collection: use ip link for determining the type of interfaces
Date: Tue, 29 Jul 2025 18:56:51 +0200 [thread overview]
Message-ID: <20250729165655.681368-7-s.hanreich@proxmox.com> (raw)
In-Reply-To: <20250729165655.681368-1-s.hanreich@proxmox.com>
Physical interfaces now can have arbitrary names with the introduction
of proxmox-network-interface pinning. In order to correctly report the
bandwidth metrics for PBS hosts, the method for determining whether an
interface is physical or not needs to be adjusted as well. Use the
adapted helper from proxmox-network-api to query the information about
interfaces and use that to determine the type of interface at every
site that uses the generated stats. To avoid spawning a new process
with every update loop, cache the initial query and use that
information.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/server/metric_collection/mod.rs | 87 +++++++++++++++++---
src/server/metric_collection/pull_metrics.rs | 5 +-
src/server/metric_collection/rrd.rs | 5 +-
3 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/src/server/metric_collection/mod.rs b/src/server/metric_collection/mod.rs
index daedfb72..9b62cbb4 100644
--- a/src/server/metric_collection/mod.rs
+++ b/src/server/metric_collection/mod.rs
@@ -1,7 +1,8 @@
use std::{
+ collections::HashMap,
path::Path,
pin::pin,
- sync::Arc,
+ sync::{Arc, OnceLock},
time::{Duration, Instant},
};
@@ -9,6 +10,7 @@ use anyhow::Error;
use tokio::join;
use pbs_api_types::{DataStoreConfig, Operation};
+use proxmox_network_api::{get_network_interfaces, IpLink};
use proxmox_sys::{
fs::FileSystemInformation,
linux::procfs::{Loadavg, ProcFsMemInfo, ProcFsNetDev, ProcFsStat},
@@ -101,7 +103,7 @@ async fn run_stat_generator() {
struct HostStats {
proc: Option<ProcFsStat>,
meminfo: Option<ProcFsMemInfo>,
- net: Option<Vec<ProcFsNetDev>>,
+ net: Option<Vec<NetdevStat>>,
load: Option<Loadavg>,
}
@@ -111,11 +113,78 @@ struct DiskStat {
dev: Option<BlockDevStat>,
}
-fn collect_host_stats_sync() -> HostStats {
- use proxmox_sys::linux::procfs::{
- read_loadavg, read_meminfo, read_proc_net_dev, read_proc_stat,
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
+enum NetdevType {
+ Physical,
+ Virtual,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
+struct NetdevStat {
+ pub device: String,
+ pub receive: u64,
+ pub send: u64,
+ pub ty: NetdevType,
+}
+
+impl NetdevStat {
+ fn from_fs_net_dev(net_dev: ProcFsNetDev, ty: NetdevType) -> Self {
+ Self {
+ device: net_dev.device,
+ receive: net_dev.receive,
+ send: net_dev.send,
+ ty,
+ }
+ }
+}
+
+static NETWORK_INTERFACE_CACHE: OnceLock<HashMap<String, IpLink>> = OnceLock::new();
+
+fn collect_netdev_stats() -> Option<Vec<NetdevStat>> {
+ use proxmox_sys::linux::procfs::read_proc_net_dev;
+
+ let net_devs = match read_proc_net_dev() {
+ Ok(net_devs) => net_devs,
+ Err(err) => {
+ eprintln!("read_prox_net_dev failed - {err}");
+ return None;
+ }
};
+ let ip_links = match NETWORK_INTERFACE_CACHE.get() {
+ Some(ip_links) => ip_links,
+ None => match get_network_interfaces() {
+ Ok(network_interfaces) => {
+ let _ = NETWORK_INTERFACE_CACHE.set(network_interfaces);
+ NETWORK_INTERFACE_CACHE.get().unwrap()
+ }
+ Err(err) => {
+ eprintln!("get_network_interfaces failed - {err}");
+ return None;
+ }
+ },
+ };
+
+ let mut stat_devs = Vec::with_capacity(net_devs.len());
+
+ for net_dev in net_devs {
+ if let Some(ip_link) = ip_links.get(&net_dev.device) {
+ let ty = if ip_link.is_physical() {
+ NetdevType::Physical
+ } else {
+ NetdevType::Virtual
+ };
+
+ stat_devs.push(NetdevStat::from_fs_net_dev(net_dev, ty));
+ }
+ }
+
+ Some(stat_devs)
+}
+
+fn collect_host_stats_sync() -> HostStats {
+ use proxmox_sys::linux::procfs::{read_loadavg, read_meminfo, read_proc_stat};
+
let proc = match read_proc_stat() {
Ok(stat) => Some(stat),
Err(err) => {
@@ -132,13 +201,7 @@ fn collect_host_stats_sync() -> HostStats {
}
};
- let net = match read_proc_net_dev() {
- Ok(netdev) => Some(netdev),
- Err(err) => {
- eprintln!("read_prox_net_dev failed - {err}");
- None
- }
- };
+ let net = collect_netdev_stats();
let load = match read_loadavg() {
Ok(loadavg) => Some(loadavg),
diff --git a/src/server/metric_collection/pull_metrics.rs b/src/server/metric_collection/pull_metrics.rs
index 3b105eaf..e99662fa 100644
--- a/src/server/metric_collection/pull_metrics.rs
+++ b/src/server/metric_collection/pull_metrics.rs
@@ -12,7 +12,7 @@ use proxmox_shared_cache::SharedCache;
use proxmox_sys::fs::CreateOptions;
use serde::{Deserialize, Serialize};
-use super::{DiskStat, HostStats, METRIC_COLLECTION_INTERVAL};
+use super::{DiskStat, HostStats, NetdevType, METRIC_COLLECTION_INTERVAL};
const METRIC_CACHE_TIME: Duration = Duration::from_secs(30 * 60);
const STORED_METRIC_GENERATIONS: u64 =
@@ -113,11 +113,10 @@ pub(super) fn update_metrics(
}
if let Some(netdev) = &host.net {
- use pbs_config::network::is_physical_nic;
let mut netin = 0;
let mut netout = 0;
for item in netdev {
- if !is_physical_nic(&item.device) {
+ if item.ty != NetdevType::Physical {
continue;
}
netin += item.receive;
diff --git a/src/server/metric_collection/rrd.rs b/src/server/metric_collection/rrd.rs
index ed39cc94..d129432e 100644
--- a/src/server/metric_collection/rrd.rs
+++ b/src/server/metric_collection/rrd.rs
@@ -16,7 +16,7 @@ use proxmox_sys::fs::CreateOptions;
use pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M;
use proxmox_rrd_api_types::{RrdMode, RrdTimeframe};
-use super::{DiskStat, HostStats};
+use super::{DiskStat, HostStats, NetdevType};
const RRD_CACHE_BASEDIR: &str = concat!(PROXMOX_BACKUP_STATE_DIR_M!(), "/rrdb");
@@ -162,11 +162,10 @@ pub(super) fn update_metrics(host: &HostStats, hostdisk: &DiskStat, datastores:
}
if let Some(netdev) = &host.net {
- use pbs_config::network::is_physical_nic;
let mut netin = 0;
let mut netout = 0;
for item in netdev {
- if !is_physical_nic(&item.device) {
+ if item.ty != NetdevType::Physical {
continue;
}
netin += item.receive;
--
2.47.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
next prev parent reply other threads:[~2025-07-29 16:56 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-29 16:56 [pbs-devel] [PATCH proxmox{-ve-rs, , -backup, -firewall, -network-interface-pinning} 0/8] proxmox-network-interface-pinning Stefan Hanreich
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox-ve-rs 1/1] host: network: move to proxmox-network-api Stefan Hanreich
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox 1/3] pbs-api-types: use proxmox-network-api types Stefan Hanreich
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox 2/3] proxmox-network-api: use ip link for querying interface information Stefan Hanreich
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox 3/3] network-api: add rename_interfaces method Stefan Hanreich
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox-backup 1/2] config: network: move to proxmox-network-api Stefan Hanreich
2025-07-29 16:56 ` Stefan Hanreich [this message]
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox-firewall 1/1] firewall: config: use proxmox-network-api Stefan Hanreich
2025-07-29 16:56 ` [pbs-devel] [PATCH proxmox-network-interface-pinning 1/1] initial commit Stefan Hanreich
2025-07-30 13:07 ` Thomas Lamprecht
2025-07-30 13:14 ` Stefan Hanreich
2025-07-30 13:24 ` Thomas Lamprecht
2025-07-30 13:30 ` Fabian Grünbichler
2025-07-30 13:35 ` Stefan Hanreich
2025-07-30 13:42 ` Thomas Lamprecht
2025-07-30 14:37 ` [pbs-devel] superseded: [PATCH proxmox{-ve-rs, , -backup, -firewall, -network-interface-pinning} 0/8] proxmox-network-interface-pinning Stefan Hanreich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250729165655.681368-7-s.hanreich@proxmox.com \
--to=s.hanreich@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.